如何使用 Ruby 中的特定步骤迭代反向范围?

Posted

技术标签:

【中文标题】如何使用 Ruby 中的特定步骤迭代反向范围?【英文标题】:How can I iterate over a reversed range with a specific step in Ruby? 【发布时间】:2013-03-20 21:06:25 【问题描述】:

我可以这样迭代

(0..10).step(2)|v| puts v

但是,由于反向范围等于空范围,我不能这样迭代

(10..0).step(2)|v| puts v

它不会给我带来任何好处。当然,我可以像这样向后迭代

10.downto(0)|v| puts v

但是 downto 方法不允许我设置除默认 1 之外的其他步骤。 这是非常基本的东西,所以我想应该有一个内置的方法来做到这一点,我不知道。

【问题讨论】:

您可以执行类似(0..10).step(2).reverse 的操作,但您可能需要添加一些逻辑,以防(10..0).step(2) 的假定输出不同。 (0..10).step(2).reverse 无效;鲁比说:NoMethodError: undefined method 'reverse' for #<Enumerator: 0..10:step(2)>. 【参考方案1】:
10.step(0, -2) do |v| puts "#v" end




10
8
6
4
2
0

【讨论】:

【参考方案2】:

你为什么不用Numeric#step:

来自文档:

使用从 num 开始的数字序列调用块,每次调用时递增(默认为 1)。当要传递给块的值大于 limit(如果 step 为正)或小于 limit(如果 step 为负)时,循环结束。如果所有参数都是整数,则循环使用整数计数器进行操作。如果任何参数是浮点数,则全部转换为浮点数,并且循环执行 floor(n + n*epsilon)+ 1 次,其中 n = (limit - num)/step。否则,循环从 num 开始,使用 运算符将计数器与 limit 进行比较,并使用 + 运算符自增。

irb(main):001:0> 10.step(0, -2) |i|把我 10 8 6 4 2 0

【讨论】:

不错。我还找到了另一种方式,虽然不太优雅: (-10..0).step(2)|v|放 -1*v【参考方案3】:

通过跳过不需要的值来模拟step 非常容易。像这样的:

10.downto(0).each_with_index do |x, idx|
  next if idx % 3 != 0 # every third element
  puts x
end
# >> 10
# >> 7
# >> 4
# >> 1

【讨论】:

如果你有条件地跳过每个语句中的元素你做错了,应该使用 select:10.downto(0).select.with_index |x, idx| idx % 3 == 0 .each |x| puts x @SamStephens:这是值得商榷的。 一切都是如此,但我会断言,如果您要使用 Ruby 的基于函数式集合的特性,您应该始终如一地使用它们,而不是混合使用函数式和命令式样式。 我认为,一旦您习惯了处理集合的功能性方法,我所获得的跨多行格式的内容更具可读性 - 您通过分离来明确分离过滤和处理select 的过滤,以及 each 的处理。 @SamStephens:我明白你的意思。如果我们从外部获得每个的主体(块参数或其他东西),那么分离过滤肯定是要走的路。在这种情况下,我会说,它们同样好。还有性能问题。我想,如果没有惰性枚举器,我的解决方案会更快。 (不过,这需要进行基准测试)

以上是关于如何使用 Ruby 中的特定步骤迭代反向范围?的主要内容,如果未能解决你的问题,请参考以下文章

Ruby:如何迭代一个范围,但以设定的增量?

问题11:如何进行反向迭代 & 如何实现反向迭代

如何将值设置为二维 Excel 范围?

如果传递了一个范围,如何实现一个函数来迭代

Ruby:如何从数组内的整数中删除特定数字?

如何在 bash 中生成步骤 n 的范围? (生成带增量的数字序列)