2 votes

Masques booléens pour vecteurs (ou itérateurs)

Quelle est la manière la plus efficace d'implémenter le masquage booléen avec des vecteurs en Rust ?

Il pourrait y avoir une crate qui fait cela(?), mais pour m'aider à apprendre, j'aimerais aussi entendre parler de :

  • comment vous le feriez sans une crate (c'est-à-dire ai-je manqué quelque chose dans la bibliothèque standard ?), et;
  • si le masquage booléen peut être étendu aux listes et aux itérateurs de manière plus générale.

Mon exemple ci-dessous applique le vecteur booléen [true, false, false, true] pour masquer les indices true d'un vecteur u32 [1, 2, 3, 4]. Cela renvoie [2, 3].

J'utilise une boucle for maladroite; pouvons-nous le faire mieux en utilisant par exemple des maps et des itérateurs ?

fn main() {
    let mut numbers = vec![1, 2, 3, 4];
    let mask = vec![true, false, false, true];

    remove_true(&mut numbers, &mask); // remove numbers where vector mask == true
    println!("{:?}", numbers)
}

// Utilisation d'une boucle for
fn remove_true(vec: &mut Vec, locs: &Vec) {
    for m in (0..locs.len()).rev() {
        // Boucle en sens inverse pour préserver les indices lors de la suppression des valeurs
        if locs[m] == true {
            vec.remove(m);
        }
    }
}

2voto

Masklinn Points 1749

Vec::retain peut être utilisé pour cette opération, en fait ce type de sélection est l'un des exemples de fragments de code :

let mut vec = vec![1, 2, 3, 4, 5];
let keep = [false, true, true, false, true];
let mut iter = keep.iter();
vec.retain(|_| *iter.next().unwrap());
assert_eq!(vec, [2, 3, 5]);

Comme vous effectuez une sélection négative (en excluant les éléments sélectionnés), vous devez inverser le résultat, mais à part cela c'est identique (en fait c'est un peu plus simple car ! ne nécessite pas de déréférencement) :

fn remove_true(vec: &mut Vec, locs: &[bool]) {
    let mut drop = locs.into_iter();
    vec.retain(|_| !drop.next().unwrap())
}

1voto

Daniel Sanchez Points 2626

Un masquage peut être abstrait comme un zip + filter sur des itérateurs aussi :

fn main() {
    let numbers = vec![1, 2, 3, 4];
    let mask = vec![true, false, false, true];

    let filtered: Vec<_> = numbers
        .iter()
        .zip(mask.iter())
        .filter_map(|(v, c)| if c { Some(v) } else { None })
        .collect();
    println!("{:?}", numbers)
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X