我想重用我制作的迭代器,以避免付费从头开始重新创建它。但是迭代器似乎没有clone
能够和collect
移动迭代器,所以我无法重复使用它。
这或多或少相当于我试图做的事情。
let my_iter = my_string.unwrap_or("A").chars().flat_map(|c|c.to_uppercase()).map(|c| Tag::from(c).unwrap() );
let my_struct = {
one: my_iter.collect(),
two: my_iter.map(|c|{(c,Vec::new())}).collect(),
three: my_iter.filter_map(|c|if c.predicate(){Some(c)}else{None}).collect(),
four: my_iter.map(|c|{(c,1.0/my_float)}).collect(),
five: my_iter.map(|c|(c,arg_time.unwrap_or(time::now()))).collect(),
//etc...
}
答案 0 :(得分:8)
在优化某些内容之前,您应该进行配置,否则您可能会使 的内容变得更慢,更复杂。
示例中的迭代器
let my_iter = my_string.unwrap_or("A").chars().flat_map(|c|c.to_uppercase()).map(|c| Tag::from(c).unwrap() );
是在堆栈上分配的瘦结构。克隆它们并不比从头开始构建它们便宜得多。
使用.chars().flat_map(|c| c.to_uppercase())
构造迭代器时,benchmark只需要一纳秒。
根据相同的基准测试,在闭包中包装迭代器创建比简单地就地构建迭代器需要更多的时间。
克隆Vec
迭代器并不比在原地构建它快得多,两者几乎都是即时的。
test construction_only ... bench: 1 ns/iter (+/- 0)
test inplace_construction ... bench: 249 ns/iter (+/- 20)
test closure ... bench: 282 ns/iter (+/- 18)
test vec_inplace_iter ... bench: 0 ns/iter (+/- 0)
test vec_clone_iter ... bench: 0 ns/iter (+/- 0)
答案 1 :(得分:5)
一般的迭代器是Clone
- 如果他们所有的"片段都是有效的。是Clone
- 能够。你在my_iter
中有几个不是:匿名闭包(如flat_map中的闭包)和to_uppercase
返回的ToUppercase结构。
你能做的是:
my_iter
收集到Vec
中(因为您似乎无论如何都要收集它):let my_iter: Vec<char> = my_string.unwrap_or("A").chars().flat_map(|c|c.to_uppercase()).map(|c| Tag::from(c).unwrap() ).collect();
my_string
的定义(因为您在其上致电unwrap_or
我认为它不是String
)而Tag
很难帮助您更具体地说。答案 2 :(得分:4)
您可以使用闭包来获得相同的迭代器:
#[derive(Debug)]
struct MyStruct{
one:Vec<char>,
two:Vec<char>,
three:String
}
fn main() {
let my_string:String = "ABCD1234absd".into();
let my_iter = || my_string.chars();
let my_struct = MyStruct{
one: my_iter().collect(),
two: my_iter().filter(|x| x.is_numeric()).collect(),
three: my_iter().filter(|x| x.is_lowercase()).collect()
};
println!("{:?}", my_struct);
}
另请参阅此Correct way to return an Iterator?问题。
你也可以克隆迭代器(参见@Paolo Falabella关于迭代器克隆性的答案):
fn main() {
let v = vec![1,2,3,4,5,6,7,8,9];
let mut i = v.iter().skip(2);
let mut j = i.clone();
println!("{:?}", i.take(3).collect::<Vec<_>>());
println!("{:?}", j.filter(|&x| x%2==0).collect::<Vec<_>>());
}
不幸的是我不知道哪种方式更有效