在 Rust 中以非标准步长遍历范围:3 种方法

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何在 Rust 中以步长 3、5 或 100 遍历数字?全面解析



想象一下:你用 Rust 编程,需要输出 0 到 20 之间的所有偶数。或者,构建一个序列 0, 5, 10, 15, 20。在 Python 中,你只需写 range(0, 21, 5) 就搞定了。那么在 Rust 中该怎么做呢?这里有一些细微之处,今天我们就来一一解析。



这个问题是 Stack Overflow 上最热门的问题之一(有数千次浏览)。这并不奇怪:标准的 for i in 0..10 只能以步长 1 工作。但如果需要其他步长呢?事实证明,总共有三种方法,每种方法都有其优点和陷阱。



我们不仅会展示代码——还会从性能、可读性和灵活性方面比较这些方法。开始吧!



为什么 Rust 没有内置带步长的 range?



简短的回答是:因为 Rust 中的 Range 是一个简单的迭代器,它生成一个整数序列。为了保持尽可能轻量和可预测,它默认不支持步长。但开发者们已经提供了解决这个问题的方法。



详细的回答是:在 Rust 生态系统中,哲学是“显式优于隐式”。创建者没有将步长塞入范围语法中,而是提供了灵活的迭代器适配工具。这提供了比看起来更多的可能性。



方法 1:step_by() —— 最直接的方式



Rust 标准库中有一个 step_by(n) 方法,它创建一个跳过每 n-1 个元素的迭代器。它的工作原理如下:



fn main() {    // 输出从 0 到 20 步长为 5 的数字    for i in (0..=20).step_by(5) {        println!("{}", i);    }    // 输出:0, 5, 10, 15, 20}


请注意:我使用了 0..=20(包含),而不是 0..20(不包含)。如果需要步长为 3 直到 10,写 (0..10).step_by(3) —— 将得到 0, 3, 6, 9。



step_by() 的优点:

  • 简单 —— 一行代码,无需闭包
  • 可读性 —— 一眼就能看出在做什么
  • 性能 —— 开销最小


缺点:

  • 仅适用于整数(i32, u64 等)
  • 无法在每次迭代中设置动态步长
  • 仅在 Rust 1.28 中引入(但这已经很久了)


这个方法对于 90% 的任务来说是理想选择。如果你只需要以固定步长遍历数字——请使用 step_by()。



方法 2:filter() —— 当步长是一个条件时



如果步长不是固定的呢?例如,需要输出能被 3 整除的数字。或者数字各位之和大于 5 的数字。这时 filter() 就派上用场了:



fn main() {    // 0 到 30 之间所有 4 的倍数    for i in (0..=30).filter(|x| x % 4 == 0) {        println!("{}", i);    }    // 输出:0, 4, 8, 12, 16, 20, 24, 28

// 现在——所有不能被 3 整除的数字 for i in (0..20).filter(|x| x % 3 != 0) { println!("{}", i); } // 输出:1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19}


这里我们传递一个闭包,它检查每个数字。filter() 只保留条件为真的元素。



何时 filter() 优于 step_by():

  • 步长取决于值(例如,“所有质数”)
  • 需要与其他条件组合
  • 步长不固定(例如,斐波那契数列)


缺点:

  • 比 step_by() 稍慢——必须检查每个数字
  • 对于初学者来说,代码可能不太直观


我个人在需要的不只是“每隔 n 个”,而是“每个符合规则的元素”时使用 filter()。它更强大,但需要更多注意

博客

书籍推荐