我可以将 Item=(key, val) 的迭代器拆分为单独的 key iter 和 val iter 而不进行收集或克隆吗?

dan*_*nda 1 iterator rust

我有一个如下所示的函数:

    fn set_many(&mut self, key_vals: impl IntoIterator<Item = (Index, T)>)
    {
        let (keys, vals): (Vec<_>, Vec<_>) = key_vals.into_iter().unzip();

        let mut viter = vals.into_iter();
        let mut iter_mut = self.many_iter_mut(keys);

        while let Some(mut setter) = iter_mut.next() {
            setter.set(viter.next().unwrap())
        }
    }

fn main() {
    let mut v = SimpleVec(vec![100, 200, 300, 400, 500]);
    
    v.set_many([(1, 20), (2, 30), (4, 50)]);
    
    println!("modified vec: {:?}", v);
}
Run Code Online (Sandbox Code Playgroud)

输出:

modified vec: SimpleVec([100, 20, 30, 400, 50])
Run Code Online (Sandbox Code Playgroud)

这是可行的,但有必要调用unzip()将键和值收集到单独的 Vec 中。对于大型集合来说,这是不可取的。

更改函数签名并接受单独的 key 和 val iter 参数将起作用。不幸的是,这个函数是公共 API 的一部分并且已经在使用中,所以我不希望在下游造成不必要的破坏。

所以我想知道是否有什么方法可以在不收集的情况下重写这个函数?

避免unwrap().

这里是一个游乐场

bk2*_*204 7

不,这根本不可能。可以增量压缩迭代器而不解压缩它们的原因实际上很容易理解:需要几乎无限的缓冲。

如果您有一个迭代器 I,您可以将其解压缩为两个迭代器 A 和 B,那么这两个迭代器必须共享对 I 的引用,因为前进 I 是获取下一个键和值的唯一方法。但是,如果您将 A 前进 100 个项目而不是 B,您仍然需要以某种方式保留从 I 的值中提取但尚未读取的 100 个 B 项目。一般来说,迭代器不会过多地缓冲其内容,因为这会增加大量的内存使用量。

另一方面,只需每次调用​​ I 时将 A 和 B 各推进一项,就可以将 A 和 B 压缩到 I 中next。这样效率就高多了,所以就实现了。