[英]What's the most efficient way to reuse an iterator in Rust?
I'd like to reuse an iterator I made, so as to avoid paying to recreate it from scratch. 我想重用我制作的迭代器,以避免付费从头开始重新创建它。 But iterators don't seem to be
clone
able and collect
moves the iterator so I can't reuse it. 但是迭代器似乎不能
clone
并且collect
会移动迭代器,所以我无法重用它。
Here's more or less the equivalent of what I'm trying to do. 这或多或少相当于我正在尝试做的事情。
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...
}
You should profile before you optimize something, otherwise you might end making things both slower and more complex than they need to. 你就应该剖析您优化前的东西,否则你可能最终使事情都慢,要复杂得多,他们需要。
The iterators in your example 示例中的迭代器
let my_iter = my_string.unwrap_or("A").chars().flat_map(|c|c.to_uppercase()).map(|c| Tag::from(c).unwrap() );
are thin structures allocated on the stack. 是堆栈上分配的瘦结构。 Cloning them isn't going to be much cheaper than building them from scratch.
克隆它们并不比从头开始构建它们便宜得多。
Constructing an iterator with .chars().flat_map(|c| c.to_uppercase())
takes only a single nanosecond when I benchmark it. 使用
.chars().flat_map(|c| c.to_uppercase())
构造一个迭代器只需要一纳秒就可以进行基准测试 。
According to the same benchmark, wrapping iterator creation in a closure takes more time than simply building the iterator in-place. 根据相同的基准测试,在闭包中包装迭代器创建比简单地就地构建迭代器需要更多的时间。
Cloning a Vec
iterator is not much faster than building it in-place, both are practically instant. 克隆
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)
Iterators in general are Clone
-able if all their "pieces" are Clone
-able. 如果所有的“碎片”都是可
Clone
那么迭代器通常是Clone
。 You have a couple of them in my_iter
that are not: the anonymous closures (like the one in flat_map) and the ToUppercase struct returned by to_uppercase
. 你在
my_iter
中有几个不是:匿名闭包(比如flat_map中的闭包)和to_uppercase
返回的ToUppercase结构。
What you can do is: 你能做的是:
my_iter
into a Vec
before populating my_struct (since you seem to collect it anyway in there): 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_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
(since you call unwrap_or
on it I assume it's not a String
) and Tag
it's hard to help you more concretely with this. my_string
的定义(因为你在它上面调用unwrap_or
我认为它不是一个String
)并且Tag
它很难用这个来更具体地帮助你。 You may use closure to get identical iterators: 您可以使用闭包来获得相同的迭代器:
#[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);
}
See also this Correct way to return an Iterator? 另请参阅这种返回迭代器的正确方法? question.
题。
Also you may clone iterator (see @Paolo Falabella answer about iterators cloneability): 你也可以克隆迭代器(参见@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<_>>());
}
Unfortunately I can't tell which way is more effective 不幸的是,我不知道哪种方式更有效
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.