Rust中迭代器和反向迭代器的向量

7ivaypg9  于 2023-02-04  发布在  其他
关注(0)|答案(2)|浏览(154)

我有一个Vec,它包含了切片上的迭代器,有些是正常顺序的,有些是相反的。

let mut output = Vec::new();
    let input = b"1234567890";
    let cuts = [(0,1), (1,3), (3, 5)];
    for (start, end) in cuts{
        output.push(input[start..end].iter());
        output.push(input[start..end].iter().rev());
    }

但是我不能编译它,因为

expected struct `std::slice::Iter`, found struct `Rev`

我理解这个错误,但是我不知道,如果我能把这两个迭代器转换成某种公共类型(不用“收集”它们)。
UPD:我甚至尝试使用.iter().rev().rev(),但它与iter().rev()是不同的类型...

wz1wpwve

wz1wpwve1#

迭代器和反向迭代器是完全不同的类型,不能直接存储在同一个向量中,它们很可能甚至大小都不一样。
当然,它们都实现了Iterator,所以你可以通过间接方式存储它们,或者作为trait对象引用(&dyn Iterator),或者作为boxed trait对象(Box<dyn Iterator>),哪一个取决于你的使用情况;第一种是间接费用少,但却是借来的;第二个具有最小的开销,但是拥有对象。
在您的例子中,由于您没有保留迭代器对象,而是希望将它们直接存储在列表中,因此正确的解决方案是使用Box<dyn Iterator>,如下所示:

fn main() {
    let mut output: Vec<Box<dyn Iterator<Item = &u8>>> = Vec::new();
    let input = b"1234567890";
    let cuts = [(0, 1), (1, 3), (3, 5)];
    for (start, end) in cuts {
        output.push(Box::new(input[start..end].iter()));
        output.push(Box::new(input[start..end].iter().rev()));
    }

    for iter in output {
        println!("{:?}", iter.collect::<Vec<_>>());
    }
}
[49]
[49]    
[50, 51]
[51, 50]
[52, 53]
[53, 52]

小毛病:
不鼓励在&u8上进行迭代,因为&u8实际上大于u8。由于u8Copy,所以将copied()添加到迭代器中可以减少项大小,而不需要任何成本;甚至很可能具有性能优势。
原因是返回&u8比返回u8慢(因为&u8是4或8字节,而u8是单字节)。此外,访问&u8有一个间接寻址,而访问u8非常快。
所以我会这样重写你的代码:
一个二个一个一个
当然,这只对&u8适用,对&mut u8不适用;如果你想改变原来的项目,复制它们会适得其反。

kb5ga3dv

kb5ga3dv2#

要将迭代器转换为通用类型,可以使用dynamic dispatch,将trait对象存储到输出向量中:

let mut output: Vec<Box<dyn Iterator<Item = _>>> = Vec::new();
let input = b"1234567890";
let cuts = [(0, 1), (1, 3), (3, 5)];
for (start, end) in cuts {
    output.push(Box::new(input[start..end].iter()));
    output.push(Box::new(input[start..end].iter().rev()));
}

Playground

相关问题