对于给定的迭代器集合a,b,c,可以使用a.chain(b).chain(c)
成功链接它们。由于我尝试编写的CLI util提供了一个路径向量(字符串, - dirs“a / b / c”“d / e / f”......),我想使用walkd_dir
他们每个人然后将他们连在一起。我的第一个想法是:
fn main() {
let a = 0..3;
let b = 3..6;
let c = 6..9;
let v = vec![b, c];
v.iter().cloned().fold(a, |acc, e| acc.chain(e));
}
<anon>:6:40: 6:52 error: mismatched types:
expected `core::ops::Range<_>`,
found `core::iter::Chain<core::ops::Range<_>, core::ops::Range<_>>`
(expected struct `core::ops::Range`,
found struct `core::iter::Chain`) [E0308]
<anon>:6 v.iter().cloned().fold(a, |acc, e| acc.chain(e));
另一次尝试http://is.gd/ZKdxZM,虽然a.chain(b).chain(c)
有效。
答案 0 :(得分:8)
使用flat_map
:
fn main() {
let a = 0..3;
let b = 3..6;
let c = 6..9;
let v = vec![a, b, c];
v.iter().flat_map(|it| it.clone());
}
答案 1 :(得分:1)
正如错误消息所述,Range
的类型与Chain<Range, Range>
的类型不同,并且调用fold
中累加器的类型必须始终保持一致。否则,如果向量中没有项目,返回类型将来自fold
?
最简单的解决方案是使用特征对象,特别是Box<Iterator>
:
type MyIter = Box<Iterator<Item=i32>>;
fn main() {
let a = 0..3;
let b = 3..6;
let c = 6..9;
let v = vec![b, c];
let z = v.into_iter().fold(Box::new(a) as MyIter, |acc, e| {
Box::new(acc.chain(Box::new(e) as MyIter)) as MyIter
});
for i in z {
println!("{}", i);
}
}
这增加了一个间接级别,但将两种具体类型(Range
,Chain
)统一为一种类型。
一个可能更有效但更长的类型版本是创建代表 enum
或Range
的{{1}},然后实现{{1对于那种新类型。
实际上,我不认为Chain
会起作用,因为它需要递归定义,这是不允许的。