在Rust中重用迭代器的最有效方法是什么?

Cam*_*rzt 6 iterator move-semantics rust

我想重用我制作的迭代器,以避免付费从头开始重新创建它.但迭代器似乎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...
}
Run Code Online (Sandbox Code Playgroud)

Art*_*mGr 8

你就应该剖析您优化前的东西,否则你可能最终使事情慢,要复杂得多,他们需要.

示例中的迭代器

let my_iter = my_string.unwrap_or("A").chars().flat_map(|c|c.to_uppercase()).map(|c| Tag::from(c).unwrap() );
Run Code Online (Sandbox Code Playgroud)

是堆栈上分配的瘦结构.克隆它们并不比从头开始构建它们便宜得多.

.chars().flat_map(|c| c.to_uppercase())在我对基准测试进行基准测试时,构造一个迭代器只需要一纳秒.

根据相同的基准测试,在闭包中包装迭代器创建比简单地就地构建迭代器需要更多的时间.

克隆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)
Run Code Online (Sandbox Code Playgroud)


Pao*_*lla 6

Clone如果它们的所有"碎片"都是Clone可用的,那么一般的迭代器是可用的.你有几个my_iter不是:匿名闭包(如flat_map中的闭包)和返回的ToUppercase结构to_uppercase.

你能做的是:

  1. 重建整个事物(如@ArtemGr建议).您可以使用宏来避免重复.有点难看,但应该工作.
  2. 在填充my_struct之前收集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();
  3. 创建自己的自定义迭代器.没有你的定义my_string(因为你打电话unwrap_or给我,我认为它不是一个String),Tag而且很难用这个更具体地帮助你.

  • 几年后,所有这些部分都已变得可克隆:https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=57f68b06d81e4f798e90c0bb8d38beea (2认同)

aSp*_*pex 5

您可以使用闭包来获得相同的迭代器:

#[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);
}
Run Code Online (Sandbox Code Playgroud)

另请参阅返回迭代器的正确方法?题。

您也可以克隆迭代器(请参阅@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<_>>());
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我不知道哪种方式更有效