rust 有没有一种简单的方法可以从数组中删除重复的元素?

lnxxn5zx  于 2022-12-19  发布在  其他
关注(0)|答案(4)|浏览(233)

我想从数组中删除重复的元素:

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},
        ]
    */
}

方法2比方法1简单,但还有更简单的吗?

uwopmtnx

uwopmtnx1#

dedupItertools中的unique方法有一个区别,前者对连续元素进行操作,即:

[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]

如果您希望name具有独特的元素,unique_by可以做到:
x一个一个一个一个x一个一个二个x

qxsslcnc

qxsslcnc2#

也许Itertools::uniqueItertools::unique_by有帮助,它们使用基于Hash的方法。

kpbpu008

kpbpu0083#

对于Nightly Rust,这可以通过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);
}

这实际上并没有“删除"重复的元素,它只是将它们移动到原始切片/ array /Vec的末尾,因为数组有固定的长度,所以不可能从数组中删除值。
另见:

hyrbngr7

hyrbngr74#

如果你不介意的话,这是一个删除重复项的简单方法,因为原始插入顺序会丢失。

let unique = std::collections::BTreeSet::from(arr);
let arr = unique.into_iter().collect::<Vec<_>>();
println!("{arr:?}");

Playground

相关问题