使用自定义函数计算结构的Vec中的部分重复项

时间:2016-06-08 09:39:36

标签: rust

所以,让我说我有以下例子:

struct Client {
    email: String,
    phone: String,
    details: String
}

fn main() {
    let mut clients: Vec<Client> = Vec::new();

    clients.push(Client {
        email: "john@gmail.com".to_string(),
        phone: "0123456789".to_string(),
        details: "custom details".to_string(),
    });

    clients.push(Client {
        email: "john@gmail.com".to_string(),
        phone: "0123456789".to_string(),
        details: "other details".to_string(),
    });

    clients.push(Client {
        email: "james@gmail.com".to_string(),
        phone: "9876543210".to_string(),
        details: "test".to_string(),
    });  
}

通过检查email中的phoneClient来计算此向量中的部分重复项的最佳(Rust惯用)方法是什么?例如 - 在上面的示例中,将找到一个副本。

2 个答案:

答案 0 :(得分:4)

一种选择是为每个客户创建一个HashSet (email, phone)。由于HashSet仅保留唯一元素,因此我们可以获得重复元素的数量,其中集合中clients的元素数量不同:

use std::collections::HashMap;

struct Client {
    email: String,
    phone: String,
    details: String,
}

fn main() {
    let mut clients: Vec<Client> = Vec::new();

    clients.push(Client {
        email: "john@gmail.com".to_string(),
        phone: "0123456789".to_string(),
        details: "custom details".to_string(),
    });

    clients.push(Client {
        email: "john@gmail.com".to_string(),
        phone: "0123456789".to_string(),
        details: "other details".to_string(),
    });

    clients.push(Client {
        email: "james@gmail.com".to_string(),
        phone: "9876543210".to_string(),
        details: "test".to_string(),
    });

    // use as_str to get a `&str` from a String to avoid copying the string
    let uniques: HashMap<_, _> = clients.iter()
        .map(|c| (c.email.as_str(), c.phone.as_str()))
        .collect();

    let num_dups = clients.len() - uniques.len();

    assert_eq!(1, num_dups);
}

答案 1 :(得分:1)

您经常想知道哪些是重复项。在这种情况下,可以使用the HashSet solution的直接扩展名:

// logger.lib : logger.c
static int s_log_level;  // only visible to logger.c
void set_log_level(int log_level) { s_log_level = log_level; }
void log(const char* mesg)        { /*...*/ }

注意在use std::collections::HashMap; struct Client { email: String, phone: String, details: String, } impl Client { fn key<'a>(&'a self) -> (&'a str, &'a str) { (&self.email, &self.phone) } } fn main() { let clients = vec![Client { email: "john@gmail.com".to_string(), phone: "0123456789".to_string(), details: "custom details".to_string(), }, Client { email: "john@gmail.com".to_string(), phone: "0123456789".to_string(), details: "other details".to_string(), }, Client { email: "james@gmail.com".to_string(), phone: "9876543210".to_string(), details: "test".to_string(), }]; let mut keyed = HashMap::new(); for c in &clients { keyed.entry(c.key()).or_insert(vec![]).push(c) } for (k, v) in &keyed { if v.len() > 1 { println!("Key {:?} has {} duplicates!", k, v.len()); } } } 上使用方法将键控逻辑保持在一个位置,使用Client来减少所需的显式可变性的数量,并且不需要指定类型可以推断出vec![]