返回由Vec <u8>的迭代器生成的元素的移动窗口

时间:2015-06-14 19:18:03

标签: iterator rust

我试图弄清楚如何从我首先过滤的矢量中返回一个元素窗口,而不将其复制到新的矢量。

所以这是天真的方法,但是我认为最终将从第5行分配一个我不想要的新矢量。

let mut buf  = Vec::new();
file.read_to_end(&mut buf);
// Do some filtering of the read file and create a new vector for subsequent processing
let iter = buf.iter().filter(|&x| *x != 10 && *x != 13);
let clean_buf = Vec::from_iter(iter);
for iter in clean_buf.windows(13) {
    print!("{}",iter.len());
}

我可以使用chain()的替代方法?无需复制到新的Vec即可实现同样的目标

for iter in buf.iter().filter(|&x| *x != 10 && *x != 13) {
    let window =  ???       
}

2 个答案:

答案 0 :(得分:4)

您可以使用Vec::retain代替filter,这样可以保留您的Vec:

fn main() {
    let mut buf = vec![
        8, 9, 10, 11, 12, 13, 14,
        8, 9, 10, 11, 12, 13, 14,
        8, 9, 10, 11, 12, 13, 14,
    ];
    println!("{:?}", buf);
    buf.retain(|&x| x != 10 && x != 13);
    println!("{:?}", buf);
    for iter in buf.windows(13) {
        print!("{}, ", iter.len());
    }
    println!("");
}

答案 1 :(得分:1)

我不知道这是怎么可能的。你说:

  

我首先过滤的矢量中的元素

但是一旦你filter编辑了一个向量,你就不再拥有一个向量 - 你只有一个IteratorIterator只有下一个项目的概念。

为了最有效率,您必须创建一个窗口大小的小缓冲区。不幸的是,您cannot write an iterator that returns a reference to itself,因此您必须将缓冲区传递给假设的Iterator::windows方法。在这种情况下,你会遇到一个问题,即有一个可变引用(所以你可以填充缓冲区)和一个不可变的引用(所以你可以返回一个切片),它不会飞。

我能想到的唯一接近的解决方案是在同一个向量上有多个迭代器然后zip在一起:

fn main() {
    let nums: Vec<u8> = (1..100).collect();

    fn is_even(x: &&u8) -> bool { **x % 2 == 0 }

    let a = nums.iter().filter(is_even);
    let b = nums.iter().filter(is_even).skip(1);
    let c = nums.iter().filter(is_even).skip(2);

    for z in a.zip(b).zip(c).map(|((a, b), c)| (a,b,c)) {
        println!("{:?}", z);
    }  
}

这有一个明显的缺点,需要多次应用过滤条件,以及嵌套拉链的丑陋(你可以使用itertools修复后者)。

就我个人而言,我可能只是collect进入Vec,就像你已经做过的那样。

相关问题