Parsing 将迭代器解交织为两个独立的迭代器

Parsing 将迭代器解交织为两个独立的迭代器,parsing,rust,iterator,stride,Parsing,Rust,Iterator,Stride,与这个问题类似: 相反,我想做相反的行为。将一个迭代器分成两个不同的迭代器,而不必收集它们的内容(也就是说,我不想使用) 此外,我想分离迭代器,而不收集原始迭代器的全部内容 下面是一个半示例: #[derive(Debug)] struct Foo(i32); fn main() { // note array elements of Foo cannot be copied or cloned // v1: [0, 1, 2, 3] // v2: [4, 5, 6,

与这个问题类似:

相反,我想做相反的行为。将一个迭代器分成两个不同的迭代器,而不必收集它们的内容(也就是说,我不想使用)

此外,我想分离迭代器,而不收集原始迭代器的全部内容

下面是一个半示例:

#[derive(Debug)]
struct Foo(i32);

fn main() {
    // note array elements of Foo cannot be copied or cloned
    // v1: [0, 1, 2, 3]
    // v2: [4, 5, 6, 7]
    let v1 = (0..4).map(|num| Foo(num)).collect::<Vec<_>>();
    let v2 = (4..8).map(|num| Foo(num)).collect::<Vec<_>>();

    // generate interleaved iterator
    // interleaved: [0, 1, 4, 5, 2, 3, 6, 7]
    let interleaved = v1.chunks(2)
        .zip(v2.chunks(2))
        .flat_map(|(c1, c2)| c1.iter().chain(c2));
        
    println!("interleaved: {:?}", interleaved.collect::<Vec<_>>());
    
    // regenerate interleaved iterator
    let interleaved = v1.chunks(2)
        .zip(v2.chunks(2))
        .flat_map(|(c1, c2)| c1.iter().chain(c2));
    
    let mut v3: Vec<&Foo> = vec![];
    let mut v4: Vec<&Foo> = vec![];
        
    for (idx, item) in interleaved.enumerate() {
        if idx % 4 < 2 {
            v3.push(item);
        } else {
            v4.push(item);
        }
    }
    
    println!("v3: {:?}, v4: {:?}", v3, v4);
}
#[派生(调试)]
结构Foo(i32);
fn main(){
//注意:无法复制或克隆Foo的数组元素
//v1:[0,1,2,3]
//v2:[4,5,6,7]
设v1=(0..4).map(|num | Foo(num)).collect::();
设v2=(4..8).map(|num | Foo(num)).collect::();
//生成交错迭代器
//交错:[0,1,4,5,2,3,6,7]
让交错=v1.块(2)
.zip(v2.块(2))
平面图(|(c1,c2)| c1.iter().链(c2));
println!((“交错:{:?}”,交错。收集::());
//重新生成交错迭代器
让交错=v1.块(2)
.zip(v2.块(2))
平面图(|(c1,c2)| c1.iter().链(c2));
让mut v3:Vec=Vec![];
让mut v4:Vec=Vec![];
for交错.enumerate()中的(idx,item){
如果idx%4小于2{
v3.推送(项目);
}否则{
v4.推送(项目);
}
}
println!(“v3:{:?},v4:{:?},v3,v4);
}
我想找到一个惯用的解决方案来取消迭代器的交错,而不必将它们的引用收集到容器中

更一般地说,我想找出如何将
n
元素的迭代器减少到
m
元素,其中
n>=m
。在本例中,我希望将长度为8的交错迭代器减少为长度为4的块为2的迭代器。然后,分块迭代器将被分成另外两个迭代器


从这个意义上说,我想将迭代器“解析”为2块。

如果原始迭代器实现了
Clone
,那么您可以克隆它并分别执行
enumerate()
+
filter()

fn uninterleave<T, I: Iterator<Item = T> + Clone>(
    iter: I,
) -> (impl Iterator<Item = T>, impl Iterator<Item = T>) {
    let iter1 = iter
        .clone()
        .enumerate()
        .filter(|(i, _)| i % 4 < 2)
        .map(|(_, value)| value);

    let iter2 = iter
        .enumerate()
        .filter(|(i, _)| i % 4 >= 2)
        .map(|(_, value)| value);

    (iter1, iter2)
}

fn main() {
    let v = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    let iter = v.iter();

    let (iter1, iter2) = uninterleave(iter);
    for value in iter1 {
        print!("{} ", value);
    }
    println!();
    for value in iter2 {
        print!("{} ", value);
    }
}

在这个操作将产生的两个迭代器中,假设您完全使用了第二个迭代器,而不使用第一个迭代器。这意味着您必须已经完全使用了原始的(分块的)迭代器,但是一半的元素仍然必须存储在某个地方(在哪里?)。我不认为你能比把它分成两个
Vec
s的解决方案做得更好。这能在不克隆迭代器的情况下完成吗?我特别想知道如何将单个迭代器拆分为两个迭代器。此解决方案对可克隆迭代器有效,但对不可克隆迭代器无效。我不知道没有克隆或收集的方法。两个迭代器都需要对原始迭代器的可变引用,这是不允许的。即使这可行,从一个迭代器构建两个迭代器的问题正如@apilat的评论所描述的:迭代一个迭代器将迭代原始迭代器,这意味着它可能跳过另一个迭代器无法恢复的值。为了避免丢失数据,您必须知道从下一个投票到哪一个,这似乎违背了目的。