Vector 连接字符串向量的向量

Vector 连接字符串向量的向量,vector,concatenation,rust,Vector,Concatenation,Rust,我正在尝试编写一个函数,它接收字符串向量的向量,并返回连接在一起的所有向量,也就是说,它返回字符串向量 到目前为止,我所能做的最好的事情是: fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> { let vals : Vec<&String> = vecs.iter().flat_map(|x| x.into_iter()).collect(); vals.in

我正在尝试编写一个函数,它接收字符串向量的向量,并返回连接在一起的所有向量,也就是说,它返回字符串向量

到目前为止,我所能做的最好的事情是:

fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    let vals : Vec<&String> = vecs.iter().flat_map(|x| x.into_iter()).collect();
    vals.into_iter().map(|v: &String| v.to_owned()).collect()
}
我在上面假设类型推断器能够根据
vals
的类型计算出
U=&String
。但如果我在代码中为表达式指定显式类型,则编译时不会出错:

fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    let a: Iter<Vec<String>> = vecs.iter();
    let b: FlatMap<Iter<Vec<String>>, Iter<String>, _> = a.flat_map(|x| x.into_iter());
    let c = b.collect();
    print_type_of(&c);
    let vals : Vec<&String> = c;
    vals.into_iter().map(|v: &String| v.to_owned()).collect()
}
我的理解是,通过使用
到iter
我将
vecs
的所有权转移到
IntoIter
并进一步转移到调用链中,这使我能够避免在lambda调用中复制数据,因此,神奇的是,type系统给了我
Vec
,而它以前总是给我
Vec
。虽然看到高级概念如何反映在库的工作中确实很酷,但我希望我知道这是如何实现的

编辑2:经过一个艰苦的猜测过程,查看API文档并使用它来破译类型,我将它们完全注释(忽略生命周期):

fn concat_vecs(vecs:Vec)->Vec{
设a:Iter=vecs.Iter();
设f:&Fn(&Vec)->Iter=&x:&Vec|x.为Iter();
设b:FlatMap Iter>=a.FlatMap(f);
让vals:Vec=b.collect();
vals.into_iter().map(|v:&String | v.to_owned()).collect()
}

我想:为什么在外部vec上使用iter(),而在内部vec上使用iter()?在iter()中使用
实际上是至关重要的,这样我们就不必先复制内部向量,然后复制内部字符串,我们只需获得它们的所有权

我们实际上可以像求和一样来写:把向量两个接一个。由于我们总是重复使用同一累积向量的分配和内容,因此此操作是线性时间

为了最大限度地减少增长和重新分配向量所需的时间,请提前计算所需的空间

fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    let size = vecs.iter().fold(0, |a, b| a + b.len());
    vecs.into_iter().fold(Vec::with_capacity(size), |mut acc, v| {
        acc.extend(v); acc
    })
}
fn concat_vecs(vecs:Vec)->Vec{
设size=vecs.iter().fold(0,| a,b | a+b.len());
vecs.into_iter().折叠(Vec::具有_容量(大小),| mut acc,v|{
附件扩展(v);附件
})
}
如果您确实想克隆所有内容,那么已经有了一种方法,您只需使用
vecs.concat()/*->Vec*/


使用
.flat\u map
的方法很好,但如果不想再次克隆字符串,则必须在所有级别上使用
.into\u iter()
:(
x
Vec

vecs.into_iter().flat_map(|x | x.into_iter()).collect()

如果您想克隆每个字符串,可以使用以下方法:(将
.into_iter()
更改为
.iter()
,因为
x
这里有一个
&Vec
,这两种方法的结果实际上是相同的!)


vecs.iter().flat|map(|x | x.iter().map(Clone::Clone)).collect()

这给了我一些错误:`build.rs:104:9:104:12错误:无法借用不可变的局部变量
acc
作为可变的build.rs:104 acc.extend(v);v^~~注意:在闭包扩展构建的扩展中。rs:103:53:105:6注意:扩展站点构建。rs:104:24:104:25错误:使用移动值:
v
[E0382]构建。rs:104 acc.extend(v);v`可能是因为我在提交后才对其进行测试编译,但后来我修复了如何独立学习vecs.concat()?它不在std::vec::vec的API页面上。我的意思是,如果查看API没有给出任何提示,我应该如何找到它?即使现在我凭经验知道它在那里,我也不知道它是在哪里定义的。尽管如此,我所追求的是学习如何独立地获得所需的结果,因此我真的想以我的代码为起点,看看如何改进它,使其只使用一个collect(),而不是重写。这回答了我的主要问题,我真的想将您的答案标记为解决方案,但是OTOH我也想得到元问题的答案(如何通过查看API找出类型)。也许我的问题太宽泛了?
-vecs.iter():iter
:这是不正确的。在struct
Iter
上没有名为
Item
的关联类型(只有traits可以有关联类型)
vecs.iter()
属于
iter
类型,但是(请注意
)。当您
flat\u map
执行此操作时,将
&Vec
转换为
&String
fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    vecs.into_iter().flat_map(|x| x.into_iter()).collect()
}
fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    let a: Iter<Vec<String>> = vecs.iter();
    let f : &Fn(&Vec<String>) -> Iter<String> = &|x: &Vec<String>| x.into_iter();
    let b: FlatMap<Iter<Vec<String>>, Iter<String>, &Fn(&Vec<String>) -> Iter<String>> = a.flat_map(f);
    let vals : Vec<&String> = b.collect();
    vals.into_iter().map(|v: &String| v.to_owned()).collect()
}
fn concat_vecs(vecs: Vec<Vec<String>>) -> Vec<String> {
    let size = vecs.iter().fold(0, |a, b| a + b.len());
    vecs.into_iter().fold(Vec::with_capacity(size), |mut acc, v| {
        acc.extend(v); acc
    })
}