将一个引用的Vec转换为值的Vec的惯用方法是什么?

25

我的函数返回一个元组的引用Vec,但我需要一个元组Vec

use std::collections::HashSet;

fn main() {
    let maxs: HashSet<(usize, usize)> = HashSet::new();
    let mins: HashSet<(usize, usize)> = HashSet::new();
    let intersection = maxs.intersection(&mins).collect::<Vec<&(usize, usize)>>();
}

我该如何进行转换?

错误:

19 |     maxs.intersection(&mins).collect::<Vec<&(usize, usize)>>()
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
   |
   = note: expected type `std::vec::Vec<(usize, usize)>`
          found type `std::vec::Vec<&(usize, usize)>`

我正在使用 for 循环进行转换,但是我不喜欢它,我认为应该有一种更符合惯用法的方式:

for t in maxs.intersection(&mins).collect::<Vec<&(usize, usize)>>().iter() {
    output.push(**t);
}
1个回答

29

从1.36.0版本更新

Rust 1.36.0引入了copied,它的工作方式类似于cloned,但使用了Copy特性,该特性要求复制操作便宜(例如仅为memcpy)。如果您有原始类型或实现了Copy的类型,则可以使用它。


要使您的示例起作用,请使用cloned,然后使用collect

let maxs: HashSet<(usize,usize)> = HashSet::new();
let mins: HashSet<(usize,usize)> = HashSet::new();
let output: Vec<(usize, usize)> = maxs.intersection(&mins).cloned().collect();

这个解决方案适用于任何实现了Clone的类型:

pub fn clone_vec<T: Clone>(vec: Vec<&T>) -> Vec<T> {
    vec.into_iter().cloned().collect()
}

如果您的函数接受一个切片,您必须使用两次cloned

pub fn clone_slice<T: Clone>(slice: &[&T]) -> Vec<T> {
    slice.iter().cloned().cloned().collect()
}

这是因为iter()返回对切片引用的迭代器,导致结果为&&T
如果您恰好有一个未实现Clone的类型,您可以使用map来模仿该行为。
pub struct Foo(u32);

impl Foo {
    fn dup(&self) -> Self {
        Foo(self.0)
    }
}

pub fn clone_vec(vec: Vec<&Foo>) -> Vec<Foo> {
    vec.into_iter().map(|f| f.dup()).collect()
}

pub fn clone_vec2(vec: Vec<&Foo>) -> Vec<Foo> {
    // this function is identical to `clone_vec`, but with another syntax
    vec.into_iter().map(Foo::dup).collect()
}

(playground)


是的,它运行得非常好!重点是在collect()之前添加一些内容而不是之后。非常好!但是(我现在只是好奇)如果我们已经有了一个引用向量,并且我们想将它们转换为值向量,那会发生什么?在这种情况下,我们应该也使用cloned()吗? - Igor Chubin
1
是的。函数ret_tup正是如此。 - hellow
这适用于实现Clone的每种类型 - 也许您可以展示通用版本,它确实适用于实现Clone的任何类型? - Shepmaster
2
“你不能使用into_iter” - 实际上你是可以使用的,这个函数确实拥有切片,只不过它也存在同样的问题。 - Shepmaster
1
@lucidbrot:“vector 迭代器遍历引用”,这不对吗?是 iter() 函数来遍历切片的。你是指这个吗?如果是,原因就在于 into_iter 会消费掉 Vec,但你只有一个借用的切片(&[T]),你没有所有权,因此只能迭代它的引用。 - hellow
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接