有没有办法做一个既不是迭代也不是线性的for循环?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有没有办法做一个既不是迭代也不是线性的for循环?相关的知识,希望对你有一定的参考价值。

我可以写一个相当于这个C代码的Rust for循环:

for(int i = 2; i <= 128; i=i*i){
    //do something
}

我只是看到了类似的东西

for i in 0..128 { /* do something */ }

要么

let v = vec![0, 1, 2, /* ... */ ];
for i in v.iter() { /* do something */ }

我应该使用while循环吗?

答案

我可以编写一个等效于此C代码的for循环:

具体而言,是的:

extern crate itertools;
for i in itertools::iterate(2, |&i| i*i).take_while(|&i| i <= 128) {
    // do something
}

但总的来说,没有。没有单一,直接等同于C的for循环的所有可能用途。如果没有办法使用迭代器编写它,那么是的,你需要使用更通用的循环形式:

{
    let mut i = 2;
    while i <= 128 {
        // do something
        i = i*i;
    }
}
另一答案

您始终可以创建一个自定义迭代器,它可以执行您需要的任何唯一序列:

struct Doubling {
    current: u64,
    max: u64,
}

impl Iterator for Doubling {
    type Item = u64;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current > self.max {
            None
        } else {
            let v = Some(self.current);
            self.current *= 2;
            v
        }
    }
}

fn main() {
    let iter = Doubling { current: 2, max: 128 };
    let values: Vec<_> = iter.collect();
    println!("{:?}", values);
}

重要的是要认识到,当值加倍超出类型的大小时,这个逻辑(就像原始的C!)有令人讨厌的边缘情况。


在这种特殊情况下,您还可以识别出您具有指数级数:

fn main() {
    let iter = (1..8).map(|p| 2i32.pow(p));
    let values: Vec<_> = iter.collect();
    println!("{:?}", values);
}

如果你想真正实验,请查看Lazy sequence generation in Rust。改编在这里:

#![feature(generators, generator_trait, conservative_impl_trait)]

use std::ops::{Generator, GeneratorState};

fn doubling(mut start: u64, max: u64) -> impl Iterator<Item = u64> {
    GeneratorIteratorAdapter(move || {
        while start <= max {
            yield start;
            start *= 2;
        }
    })
}

fn main() {
    let iter = doubling(2, 128);
    let sum: Vec<_> = iter.collect();
    println!("{:?}", sum);
}

/* copy-pasta */
struct GeneratorIteratorAdapter<G>(G);

impl<G> Iterator for GeneratorIteratorAdapter<G>
where
    G: Generator<Return = ()>,
{
    type Item = G::Yield;

    fn next(&mut self) -> Option<Self::Item> {
        match self.0.resume() {
            GeneratorState::Yielded(x) => Some(x),
            GeneratorState::Complete(_) => None,
        }
    }
}

以上是关于有没有办法做一个既不是迭代也不是线性的for循环?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 for-each 循环迭代开始之前避免空检查? [复制]

foreach 循环是不是从字面上重写为带有迭代器的 for 循环? [复制]

for 循环是不是在每次迭代中重新评估其主体中的函数?

for 循环的“计数限制”表达式是不是只计算一次,还是在每次迭代时计算?

有没有办法在 Java for-each 循环中访问迭代计数器?

迭代 4 个 pandas 数据框列并将它们存储到 4 个列表中,其中一个 for 循环而不是 4 个 for 循环