给定一个结构如下:
#[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个解决方案:
&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)
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)
我想知道是否有更好的方法来过滤向量而不失去所有权。
克隆初始向量。我更喜欢这个,但它会导致不必要的克隆,我更喜欢仅克隆过滤后的项目:
&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分配更昂贵。只有当类型很大和/或包含堆分配的数据时,克隆才成为需要回避的事情。