我可以像这样迭代
(0..10).step(2){|v| puts v}
因为反向范围等于空范围,所以我不能以这种方式迭代。
(10..0).step(2){|v| puts v}
这将对我毫无收益。当然,我可以像这样向后迭代。
10.downto(0){|v| puts v}
但是downto方法不允许我设置除了默认的1以外的其他步长。这是非常基本的事情,所以我想应该有一种内置的方式可以实现这个功能,但我不知道怎么做。
为什么不使用Numeric#step
:
来自文档:
在每次调用时,使用从num开始以step(默认为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| puts i } 10 8 6 4 2 0
通过跳过不需要的值来模拟 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
10.downto(0).select.with_index { |x, idx| idx % 3 == 0 }.each { |x| puts x }
- SamStephenseach
完全是命令式的。而 downto
生成器只是一种绕过性的解决方法。 - Sergio Tulentsev10.step(0, -2) do |v| puts "#{v}" end
10
8
6
4
2
0
(0..10).step(2).reverse
,但是如果从(10..0).step(2)
中输出的结果不同,你可能需要添加一些逻辑。 - jvnill(0..10).step(2).reverse
不是有效的代码;Ruby 报错:NoMethodError: undefined method 'reverse' for #<Enumerator: 0..10:step(2)>
。 - the Tin Man