简体   繁体   English

Rust 在同一行代码上加入过滤器和 map

[英]Rust join filter and map on the same line of code

I want to change the value of a specific attribute of a vector of objects.我想更改对象向量的特定属性的值。
my code and logic are as follows:我的代码和逻辑如下:

let mut person_found: Vec<Person> = persons.clone().into_iter().filter(|x| x.id == "3")
                       .map(|x| x.name = "Carlos".to_string()).collect();

println!("original: {:?}", &persons);
println!("modified person: {:?}", &person_found);

But it gives me the following error and I can't understand it well.但它给了我以下错误,我不能很好地理解它。

error[E0277]: a value of type `Vec<Person>` cannot be built from an iterator over elements of type `()`
  --> src\main.rs:17:45
   |
17 |     .map(|x| x.name = "Carlos".to_string()).collect();
   |                                             ^^^^^^^ value of type `Vec<Person>` cannot be built from `std::iter::Iterator<Item=()>`
   |
   = help: the trait `FromIterator<()>` is not implemented for `Vec<Person>`

The result of an assignment is () (the unit value) .赋值的结果是() (单位值) So if you do y = (x = 123);所以如果你做y = (x = 123); then x is assigned 123 and y is assigned () .然后x被分配123y被分配()

The Rust Reference has a short sentence stating: Rust 参考有一个简短的句子说明:

An assignment expression always produces the unit value .赋值表达式总是产生单位值

Assignment expressions - Operator expressions - The Rust Reference 赋值表达式 - 运算符表达式 - Rust 参考

You need to change so it explicitly returns x on the next line, for that to work.您需要进行更改,以便它在下一行显式返回x ,以使其正常工作。 If you want to mutate x then you also need to change |x|如果你想改变x那么你还需要改变|x| to |mut x||mut x| . .

let person_found: Vec<Person> = persons
    .clone()
    .into_iter()
    .filter(|x| x.id == "3")
    .map(|mut x| {
        x.name = "Carlos".to_string();
        x
    })
    .collect();

Alternatively, instead of cloning the whole persons Vec upfront, I'd instead use cloned() after filter() or clone() in map() , ie only when needed.或者,我不是预先克隆整个persons Vec ,而是在map()中的filter()clone() cloned() ) ,即仅在需要时使用。

let person_found: Vec<Person> = persons
    .iter()
    .filter(|x| x.id == "3")
    .cloned()
    .map(|mut x| {
        x.name = "Carlos".to_string();
        x
    })
    .collect();

You are returning nothing in your map expr line.您在 map expr 行中没有返回任何内容。 You can handle with filter_map though:您可以使用filter_map处理:

let mut person_found: Vec<Person> = persons
    .iter()
    .filter_map(|p| {
        if p.id == "3" {
            Some(Person {
                name: String::from("Carlos"),
                ..p.clone()
            })
        } else {
            None
        }
    })
    .collect();

Playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM