加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

slice :: chunks / windows是否有等效的迭代器循环对,三元组等?

发布时间:2020-12-14 04:12:20 所属栏目:Windows 来源:网络整理
导读:一次迭代多个变量,重叠( slice::windows )或不重叠( slice::chunks )可能很有用. 这仅适用于切片;是否可以为迭代器执行此操作,为方便起见使用元组? 可以写下以下内容: for (prev,next) in some_iter.windows(2) { ...} 如果没有,它可以作为现有迭代器的特
一次迭代多个变量,重叠( slice::windows)或不重叠( slice::chunks)可能很有用.

这仅适用于切片;是否可以为迭代器执行此操作,为方便起见使用元组?

可以写下以下内容:

for (prev,next) in some_iter.windows(2) {
    ...
}

如果没有,它可以作为现有迭代器的特征实现吗?

TL; DR:在任意迭代器/集合上拥有块和窗口的最佳方法是首先将它收集到Vec中并迭代它.

在Rust中,所要求的确切语法是不可能的.

问题是在Rust中,函数的签名取决于类型,而不是值,并且存在Dependent Typing时,实现它的语言很少(很难).

这就是为什么块和窗口返回子切片的原因; & [T]中的元素数量不是类型的一部分,因此可以在运行时决定.

让我们假装你要求:for some_iter.windows(2)中的切片然后.

支持这片的存储在哪里?

它无法生存:

>在原始集合中,因为LinkedList没有连续的存储
>在迭代器中,由于Iterator :: Item的定义,没有可用的生命周期

因此,不幸的是,切片只能在后备存储是切片时使用.

如果接受动态分配,则可以使用Vec< Iterator :: Item>作为分块迭代器的项目.

struct Chunks<I: Iterator> {
    elements: Vec<<I as Iterator>::Item>,underlying: I,}

impl<I: Iterator> Chunks<I> {
    fn new(iterator: I,size: usize) -> Chunks<I> {
        assert!(size > 0);

        let mut result = Chunks {
           underlying: iterator,elements: Vec::with_capacity(size)
        };
        result.refill(size);
        result
    }

    fn refill(&mut self,size: usize) {
        assert!(self.elements.is_empty());

        for _ in 0..size {
            match self.underlying.next() {
                Some(item) => self.elements.push(item),None => break,}
        }
    }
}

impl<I: Iterator> Iterator for Chunks<I> {
    type Item = Vec<<I as Iterator>::Item>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.elements.is_empty() {
            return None;
        }

        let new_elements = Vec::with_capacity(self.elements.len());
        let result = std::mem::replace(&mut self.elements,new_elements);

        self.refill(result.len());

        Some(result)
    }
}

fn main() {
    let v = vec!(1,2,3,4,5);

    for slice in Chunks::new(v.iter(),2) {
        println!("{:?}",slice);
    }
}

将返回:

06001

精明的读者会意识到我偷偷地从窗户切换到了大块.

窗口更难,因为它多次返回相同的元素,这要求元素是克隆.此外,由于每次都需要返回完整的Vec,因此需要在内部保持Vec< Vec< Iterator :: Item>>.

这留给读者练习.

最后,关于性能的说明:所有这些分配都会受到伤害(特别是在Windows案例中).

最好的分配策略通常是分配一块内存然后实现(除非数量非常大,在这种情况下需要流式传输).

它在Rust中称为collect ::< Vec< _>>().

并且由于Vec具有块和窗口方法(通过实现Deref< Target = [T]>),因此您可以使用它:

for slice in v.iter().collect::<Vec<_>>().chunks(2) {
    println!("{:?}",slice);
}

for slice in v.iter().collect::<Vec<_>>().windows(2) {
    println!("{:?}",slice);
}

有时最好的解决方案是最简单的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读