过滤向量而不失去其所有权

Lon*_*hai 1 rust

给定一个结构如下:

#[derive(Debug)]
struct Item {
    id: u32
}

impl Item {
    fn new(id: u32) -> Item {
        Item { id }
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种方法来对该结构的向量执行过滤而不获取其所有权。以下代码将不起作用,因为所有权已转移:

fn main() {
    let items: Vec<Item> = vec![Item::new(1), Item::new(2), Item::new(3)];
    let odd_items: Vec<Item> = items.into_iter()
            .filter(| item | item.id % 2 == 1)
            .collect();
    for i in odd_items.iter() { println!("{:?}", i); }

    for i in items.iter() { println!("{:?}", i); }
}
Run Code Online (Sandbox Code Playgroud)

目前,我有2个解决方案:

  1. 然而,用 的向量&Item代替,我发现从 开始但以 结束Item有点尴尬:Vec<Item>Vec<&Item>
fn main() {
    let items: Vec<Item> = vec![Item::new(1), Item::new(2), Item::new(3)];
    let odd_items: Vec<Item> = items.into_iter()
            .filter(| item | item.id % 2 == 1)
            .collect();
    for i in odd_items.iter() { println!("{:?}", i); }

    for i in items.iter() { println!("{:?}", i); }
}
Run Code Online (Sandbox Code Playgroud)
  1. 克隆初始向量。我更喜欢这个,但它会导致不必要的克隆,我更喜欢仅克隆过滤后的项目:
fn main() {
    let items: Vec<Item> = vec![Item::new(1), Item::new(2), Item::new(3)];
    let odd_items: Vec<Item> = items.clone()
            .into_iter()
            .filter(| item | item.id % 2 == 1)
            .collect();
    for i in odd_items.iter() { println!("{:?}", i); }

    for i in items.iter() { println!("{:?}", i); }
}
Run Code Online (Sandbox Code Playgroud)

我想知道是否有更好的方法来过滤向量而不失去所有权。

use*_*342 7

克隆初始向量。我更喜欢这个,但它会导致不必要的克隆,我更喜欢仅克隆过滤后的项目:

&Item如果你想在过滤后克隆,你当然可以这样做,并且它会产生转换为的副作用Item(这就是clone()定义的作用):

let items: Vec<Item> = vec![Item::new(1), Item::new(2), Item::new(3)];
let odd_items: Vec<Item> = items
    .iter()
    .filter(|item| item.id % 2 == 1)
    .cloned()     // the same as .map(Item::clone)
    .collect();
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您可以摆脱Vec<&Item>,该解决方案可能会更有效,因为它使用更少的空间(如果实际项目大于指针),并且它创建odd_items为 的“视图” items。如果这不是您想要的,那么就进行克隆,您只需添加#[derive(Clone)]Item.

另请注意,尽管它的名声不好,但clone()并不一定很昂贵 - “克隆”struct仅包含 a 的 au32并不比u32分配更昂贵。只有当类型很大和/或包含堆分配的数据时,克隆才成为需要回避的事情。