【问题标题】:Idiomatic way to Find Struct in Struct Vec, then Perform Trait Function on that Struct in Rust在 Struct Vec 中查找结构的惯用方法,然后在 Rust 中对该结构执行特征函数
【发布时间】:2021-01-23 10:42:08
【问题描述】:

在我的项目中,我经常遍历结构向量以通过某个字段值查找对象,然后对该对象使用某些特征函数:

pub struct Person{
    name: String,
    age: u32,
    id: u32,
}

impl Person{
    pub fn new(name: String, id_num: u32, age: u32)->Self{
        let p = Person{
            name: name,
            id: id_num,
            age: age,
        };
        p
    }
}

trait PersonTrait{
    fn printname();
    fn get_name()->String; 
    fn get_age()->u32;
    fn set_age(age: u32);
}


impl PersonTrait for Person{
    fn printname(){
        dbg!(self.name)
    }
    fn get_name()->String{
        self.name
    }
    fn get_id()->u32{
        self.id;
    }
    fn set_age(age: u32){
        self.age = age;
    }
}


fn main(){
    let my_people = vec![Person::new("Rakim".to_string(), 1, 56), Person::new("Ghostface".to_string(), 2, 56), Person::new("RZA".to_string(), 3, 56)];
    //frequently repeating this pattern of finding struct in array of structs, then doing something to that found struct

    for person in my_people.clone(){
        if person.get_id() == 1 {
            person.set_age(100);
        }
    }

    for person in my_people.clone(){
        if person.get_id() == "Rakim".to_string(){
            person.printname();
        }
    }
    
}

所以我在这里使用的一般模式是:

for x in my_objects{
    if x.id() == some_id{
        x.do_some_trait_function()
    }
}

我想创建一个更通用的函数来简化这种语法,例如:

//not sure what the correct syntax would be here, or how you might pass a trait function as an argument
fn find_then_do_trait_function(obj_list: Vec<Person>, id: u32, trait_function: my_trait_function()){ 
    for x in obj_list(){
        if x.get_id() == id {
            //use my trait function on x
        }
    }
}

我该怎么做?我知道我可以为每个特征函数创建一个enum,然后为该枚举创建一个match,但这似乎也很冗长。

【问题讨论】:

    标签: rust


    【解决方案1】:

    特征函数没有什么独特之处。您已经确定了一个非常常见的模式,它可以分为两部分:我们要过滤一个向量,然后对每个匹配的元素执行一些操作。我们可以定义一个接受两个闭包参数的函数来为我们做这件事。

    fn search_and_call<T>(obj_list: &mut Vec<T>,
                          mut condition: impl FnMut(&mut T) -> bool,
                          mut func: impl FnMut(&mut T) -> ()) {
        for x in obj_list {
            if condition(x) {
              func(x);
            }
        }
    }
    

    func 可以是任何闭包。该闭包可能会调用一个特征函数,或者它可能会打印到屏幕上,或者做很多事情。上述函数的编写者不必关心;就我们而言,一切都是一样的。示例用法:

    let mut v = vec!(1, 2, 3, 4);
    search_and_call(&mut v, |x| *x % 2 == 0, |x| println!("{}", *x));
    

    然而,值得注意的是,Rust 出色的 Iterator trait 定义了大量有用的函数,我们可以免费获得这种行为,甚至无需触及 for 循环。

    let mut v = vec!(1, 2, 3, 4);
    v.iter().filter(|x| *x % 2 == 0).for_each(|x| println!("{}", *x));
    

    .iter() 在我们的向量上获得一个迭代器,.filter(...) 产生一个新的迭代器,它根据我们的条件选择某些元素,.for_each(...) 对过滤后剩余的所有元素调用一个函数。

    【讨论】:

    • 你能提供一个在闭包中调用特征函数的例子吗?我不确定语法
    • v.iter().for_each(|x| x.some_trait_function()) 像往常一样简单地调用它,只是在闭包参数上。类型推断将完成剩下的工作。
    猜你喜欢
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多