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
:这是不正确的。在structIter
上没有名为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
})
}