es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo iterar elementos de un hashmap entre ellos mismos y permitir que sean mutables?

Así que tengo un hashmap que utiliza cadenas como claves y los valores son mi propia estructura para usuarios. Que son solo su nombre y posición.

pub struct User {
    name: String,
    x: i32,
    y: i32
}

Ahora lo que quiero hacer es iterar sobre el hashmap llamado “users” y comprobar si las posiciones de dos usuarios están cerca, y luego separarlos.

for (key, userA) in self.users.iter_mut() {
    for (key, userB) in self.users.iter_mut() {
        // el código de colisión iría aquí
    }
}

Esto causa un problema porque los usuarios son prestados dos veces como mutables. Pensé en solucionar este problema usando un mutex,

for (key, userA) in self.users.lock().unwrap().iter_mut() {
    for (key, userB) in self.users.lock().unwrap().iter_mut() {
        // el código de colisión iría aquí
    }
}

y el código compila, pero causa un error en tiempo de ejecución más adelante cuando realmente agrego un usuario al mapa debido al segundo bucle, ya que si comento ese bucle, el código se ejecuta sin problemas. ¿Alguna idea de cómo podría escribir esto de manera diferente?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Como experto en TI especializado en Rust y reglas de préstamo, recomendaría usar un enfoque diferente para lograr tu objetivo de separar a dos usuarios si sus posiciones están cerca. Aquí tienes dos posibles soluciones:

    1. Usa un Vec<user> en lugar de un HashMap<string, user="">.

    Si no necesitas acceder a los usuarios por sus claves, puedes utilizar un vector para almacenarlos en su lugar. Esto te permitirá iterar sobre el vector solo una vez, sin ningún problema de préstamo:

    for i in 0..self.users.len() {
        for j in i+1..self.users.len() {
            let userA = &mut self.users[i];
            let userB = &mut self.users[j];
            // el código de colisión iría aquí
        }
    }
    

    Ten en cuenta que utilizamos índices en lugar de referencias directamente para evitar problemas de préstamo.

    1. Usa RefCell y RefMut para tomar prestados los usuarios de manera más flexible.

    Si realmente necesitas usar un hashmap, puedes utilizar RefCell y RefMut para tomar prestados los usuarios de manera más flexible. Esto te permite tomarlos prestados como inmutables o mutables según sea necesario, sin violar las reglas de préstamo de Rust:

    for (key, userA_cell) in self.users.iter() {
        let mut userA = userA_cell.borrow_mut();
        for (key, userB_cell) in self.users.iter() {
            if key != userA.key { // para evitar la autocolisión
                let mut userB = userB_cell.borrow_mut();
                // el código de colisión iría aquí
            }
        }
    }
    

    Ten en cuenta que necesitamos comparar las claves para evitar la autocolisión, ya que el mismo usuario podría tomarse prestado dos veces de esta manera.

    En resumen, utilizando un Vec<user> o RefCell y RefMut, puedes evitar problemas de préstamo y lograr tu objetivo.</string,>

Comments are closed.