0
votes

Existe-t-il un moyen simple de supprimer les éléments en double d'un tableau?

Je souhaite supprimer les éléments en double d'un tableau:

use itertools::Itertools;
use std::collections::HashSet;

#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}

fn main() {
    let arr = [
        Person { name: "aaa".to_string(), age: 10 },
        Person { name: "bbb".to_string(), age: 20 },
        Person { name: "bbb".to_string(), age: 20 },
        Person { name: "ccc".to_string(), age: 30 },
    ];

    // Way 1:
    let arr2 = {
        let names: Vec<_> = arr.iter().map(|v| v.name.clone()).unique().collect();
        names
            .iter()
            .map(|name| arr.iter().find(|person| &person.name == name).unwrap())
            .collect::<Vec<_>>()
    };
    dbg!(arr2);

    // Way 2:
    let arr2 = {
        let mut names = HashSet::new();
        arr.iter()
            .filter(|p| names.insert(p.name.clone()))
            .collect::<Vec<_>>()
    };
    dbg!(arr2);

    /*
    expect:
        [
            Person{name: "aaa".to_string(), age: 10},
            Person{name: "bbb".to_string(), age: 20},
            Person{name: "ccc".to_string(), age: 30},
        ]
    */
}

La voie 2 est simple par rapport à la voie 1, mais y a-t-il quelque chose de plus simple?


3 commentaires

Jetez un œil à vec: dedup () Si vous voulez simplement supprimer les éléments contigus dupliqués. Si la commande ne vous dérange pas, vec.sort_by (), puis vec: dedup ()


@ Iñigo dedup_by ou dedup_by_key serait plus applicable car ils souhaitent effectuer une déduplication en fonction du nom, et non de la structure Person.


Une autre option serait d'utiliser un wrapper implémentant Hash et Eq délégué à name (l'implémenter directement sur Person semble être une idée terrible), puis obtenir le tout via HashSet , ou IndexMap::IndexSet pour garder l'ordre, et éventuellement revenir à un vecteur.


3 Réponses :


1
votes

Peut-être que Itertools::unique et Itertools::unique_by help. Ils utilisent une approche basée sur le Hash .


0 commentaires

3
votes

Il y a une différence entre la méthode dedup et unique dans Itertools , où la première opère sur des éléments contigus, c'est-à-dire:

[
  Person { name: "aaa", age: 10 },
  Person { name: "bbb", age: 20 },
  Person { name: "ccc", age: 30 }
]

Si vous cherchez à avoir des éléments uniques par name , unique_by pourrait faire:

use itertools::Itertools;

#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}

fn main() {
    let arr = [
        Person { name: "aaa".to_string(), age: 10 },
        Person { name: "bbb".to_string(), age: 20 },
        Person { name: "bbb".to_string(), age: 20 }, // Duplicate
        Person { name: "ccc".to_string(), age: 30 },
    ];

    let res = arr.iter().unique_by(|p| &p.name).collect::<Vec<_>>();
}
[1, 2, 2, 3, 4, 3, 2, 1].iter().dedup()  // [1, 2, 3, 4, 3, 2, 1]
[1, 2, 2, 3, 4, 3, 2, 1].iter().unique() // [1, 2, 3, 4]


1 commentaires

Il convient également de noter que l'approche unique et op repose sur le clonage de quelque chose, alors que unique_by peut fonctionner sur des références. Honnêtement, je ne sais pas pourquoi unique repose sur le clonage de l'ensemble alors qu'il pourrait tout aussi facilement se fier à une simple référence.



1
votes

Avec Nightly Rust, cela peut être fait sur place et sans allocation de mémoire supplémentaire via slice::partition_dedup_by :

#![feature(slice_partition_dedup)]

#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}

fn main() {
    let mut arr = [
        Person { name: "aaa".to_string(), age: 10 },
        Person { name: "bbb".to_string(), age: 20 },
        Person { name: "bbb".to_string(), age: 20 },
        Person { name: "ccc".to_string(), age: 30 },
    ];

    arr.sort_by(|a, b| a.name.cmp(&b.name));
    let (unique, _) = arr.partition_dedup_by(|a, b| a.name == b.name);
    
    dbg!(unique);
}

Cela ne supprime pas réellement les éléments en double, cela les déplace simplement à la fin de la tranche / tableau / Vec . Il est impossible de supprimer des valeurs d'un tableau car un tableau a une longueur fixe.

Voir également:


0 commentaires