如何使用 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
:
来自文档:
irb(main):001:0> 10.step(0, -2) |i|把我 10 8 6 4 2 0使用从 num 开始的数字序列调用块,每次调用时递增(默认为 1)。当要传递给块的值大于 limit(如果 step 为正)或小于 limit(如果 step 为负)时,循环结束。如果所有参数都是整数,则循环使用整数计数器进行操作。如果任何参数是浮点数,则全部转换为浮点数,并且循环执行 floor(n + n*epsilon)+ 1 次,其中 n = (limit - num)/step。否则,循环从 num 开始,使用 运算符将计数器与 limit 进行比较,并使用 + 运算符自增。
【讨论】:
不错。我还找到了另一种方式,虽然不太优雅: (-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 中的特定步骤迭代反向范围?的主要内容,如果未能解决你的问题,请参考以下文章