gpt4 book ai didi

loops - 是否可以在不创建特殊迭代器的情况下每次迭代步进不同的量?

转载 作者:行者123 更新时间:2023-11-29 08:05:10 25 4
gpt4 key购买 nike

在 C 中,for 循环有一个可选的增量部分,我有时会在 Rust 中错过它:

for (uint i = 0; i < max; i = step_function(i, j, k)) {
/* many lines of code! */
}

这可以用 Rust 写成:

let mut i: u32 = 0;
while (i < max) {
//
// many lines of code!
//
i = step_function(i, j, k);
}

... 但是,如果 continue 存在于“多行代码” 中,这将引入错误。我个人的偏好也是将增量保持在循环的顶部。

在不创建特殊的迭代器来处理这个问题的情况下,有没有一种方法可以更接近地匹配 C 风格的循环,同时解决上述两个问题?

“特殊迭代器”是指不必在 for 循环之外定义迭代器类型和方法。

虽然这看起来像是一个人为的要求,但必须为单次使用定义一个迭代器 - 在阅读和编写代码时都会增加一些开销。

虽然@kennytm 的回答显示了可重用的 StepByFn 迭代器如何工作,但使用闭包会为代码添加一些否则不存在的约束。

最佳答案

如果你可以导入一个外部包,你应该使用 itertools::iterate :

extern crate itertools;
use itertools::iterate;

fn main() {
for i in iterate(0, |i| 2*i + 3).take_while(|i| *i < 100) {
println!("{}", i);
// 0 3 9 21 45 93
}
}

如果您真的缺少 C 风格的 for 循环,您可以使用 cfor crate :

#[macro_use] extern crate cfor;

fn main() {
cfor!{ let mut i = 0; i < 100; i = 2*i + 3; {
println!("{}", i);
// 0 3 9 21 45 93
}}
}

如果您仅限于使用标准库,创建一个特殊的迭代器将是最惯用的方法。

fn main() {
for i in StepByFn::new(0, 100, |i| 2*i + 3) {
println!("{}", i);
// 0 3 9 21 45 93
}
}

struct StepByFn<T, F> {
begin: T,
end: T,
step: F,
}

impl<T, F: FnMut(&T) -> T> StepByFn<T, F> {
pub fn new(begin: T, end: T, step: F) -> StepByFn<T, F> {
StepByFn { begin, end, step }
}
}

impl<T: PartialOrd, F: FnMut(&T) -> T> Iterator for StepByFn<T, F> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.begin >= self.end {
return None;
}
let next = (self.step)(&self.begin);
let prev = std::mem::replace(&mut self.begin, next);
Some(prev)
}
}

也可以用repeat().scan()创建一个内联迭代器,但是很丑,而且不能很好地表达意图

use std::iter::repeat;

fn main() {
for i in repeat(()).scan(0, |i, ()| {
let old = *i;
*i = 2*old + 3;
if old < 100 { Some(old) } else { None }
}) {
println!("{}", i);
// 0 3 9 21 45 93
}
}

关于loops - 是否可以在不创建特殊迭代器的情况下每次迭代步进不同的量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43823042/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com