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

问题描述 投票:0回答:1

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

    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);
}

输出:

modified vec: SimpleVec([100, 20, 30, 400, 50])

这是可行的,但有必要调用

unzip()
来将键和值收集到单独的 Vec 中。对于大型收藏,这是不可取的。

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

所以我想知道是否有任何方法可以重写这个函数而不需要收集?

避免

unwrap()
也很好。

这里是一个游乐场

rust iterator
1个回答
0
投票

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

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

另一方面,只需每次调用 I 的

next
,将 A 和 B 各推进一个项目,就可以将 A 和 B 压缩到 I 中。这样效率高很多,所以就实现了。

© www.soinside.com 2019 - 2024. All rights reserved.