在不创建临时向量的情况下迭代成对的块

时间:2015-06-13 21:03:34

标签: iterator rust

我正在尝试将一个向量迭代为一对块(在我的例子中,它是一个表示为连续位图的图像,我希望能够同时访问两行中的像素)。

问题是我无法做.chunks(w).chunks(2),但必须在两者之间创建一个临时向量。

有没有办法纯粹使用迭代器? (如果结果是迭代器本身,我很好)

playground

let input: Vec<_> = (0..12).collect();

let tmp: Vec<_> = input.chunks(3).collect();
let result: Vec<_> = tmp.chunks(2).collect();

println!("{:?}", result);
  

[[[0,1,2],[3,4,5]],[[6,7,8],[9,10,11]]]

4 个答案:

答案 0 :(得分:5)

  

哦,我知道了!我可以拆分更大的块:

     

input.chunks(2*3).map(|dbl| dbl.split_at(3)).collect();

是的,或者你可以这样做:

let tmp: Vec<_> = input
    .chunks(2 * 3)
    .map(|x| x.chunks(3).collect::<Vec<_>>())
    .collect();

这与您的示例完全相同,没有您的解决方案中的元组和数组的混合:

[[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]]

答案 1 :(得分:4)

这是一个创建两个迭代器的解决方案,一个用于奇数行,一个用于偶数行。然后使用.zip()组合两者,它给出一个充满对的迭代器:

fn main() {
    let input: Vec<_> = (0..12).collect();

    let it1 = input
        .chunks(3)
        .enumerate()
        .filter_map(|x| if x.0 % 2 == 0 { Some(x.1) } else { None });
    let it2 = input
        .chunks(3)
        .enumerate()
        .filter_map(|x| if x.0 % 2 != 0 { Some(x.1) } else { None });

    let r: Vec<_> = it1.zip(it2).collect();

    println!("{:?}", r);
}

答案 2 :(得分:3)

确实chunk(a).chunk(b)是不可能的,因为chunk()仅在切片上可用,而chunk()(a Chunk)的结果不是切片。这太糟糕了,我不知道是什么阻止了chunk在常规Iterator上实现。 (也许是终身问题?)

一个更详细的解决方案,但仍然以迭代器为导向(即,不会回到丑陋的C ++ - 如收集循环)将使用itertools包,更具体地说是方法batching()。这是文档中的示例,它与chunk(2)几乎完全相同,只是它返回一个元组而不是切片:

extern crate itertools;

use itertools::Itertools;

fn main() {
    // An adaptor that gathers elements up in pairs
    let pit = (0..4).batching(|it| match it.next() {
        None => None,
        Some(x) => match it.next() {
            None => None,
            Some(y) => Some((x, y)),
        },
    });

    itertools::assert_equal(pit, vec![(0, 1), (2, 3)]);
}

答案 3 :(得分:3)

哦,我知道了!我可以拆分更大的块:

input
   .chunks(2 * 100)
   .map(|pair| pair.split_at(100))