fif*_*uri 98 ruby iteration range
我尝试使用Range并向后迭代each
:
(4..0).each do |i|
puts i
end
==> 4..0
Run Code Online (Sandbox Code Playgroud)
迭代通过0..4
写入数字.在另一个范围r = 4..0
似乎没问题r.first == 4
,r.last == 0
.
我觉得上面的结构不能产生预期的结果似乎很奇怪.这是什么原因?这种行为合理的情况是什么?
Joh*_*lla 93
范围就是:由开始和结束定义的东西,而不是其内容.在一般情况下,在一个范围内"迭代"并不真正有意义.例如,考虑如何"迭代"两个日期产生的范围.你会白天迭代吗?按月?一年?一周?它没有明确定义.IMO,它允许前进范围的事实应该被视为一种便利方法.
如果你想在这样的范围内向后迭代,你总是可以使用downto
:
$ r = 10..6
=> 10..6
$ (r.first).downto(r.last).each { |i| puts i }
10
9
8
7
6
Run Code Online (Sandbox Code Playgroud)
以下是来自其他人的更多想法,为什么很难同时允许迭代并始终处理反向范围.
Jon*_*röm 18
迭代Ruby中的一个范围,each
调用该范围中succ
第一个对象的方法.
$ 4.succ
=> 5
Run Code Online (Sandbox Code Playgroud)
并且5超出范围.
您可以使用此hack模拟反向迭代:
(-4..0).each { |n| puts n.abs }
Run Code Online (Sandbox Code Playgroud)
约翰指出,如果它跨越0,这将不起作用.这将:
>> (-2..2).each { |n| puts -n }
2
1
0
-1
-2
=> -2..2
Run Code Online (Sandbox Code Playgroud)
不能说我真的喜欢他们中的任何一个,因为他们有点模糊了意图.
bta*_*bta 12
根据"Programming Ruby"一书,Range对象存储范围的两个端点,并使用该.succ
成员生成中间值.根据您在您的范围内使用的数据类型,您始终可以创建一个子类Integer
并重新定义该.succ
成员,使其像反向迭代器一样(您可能也想要重新定义.next
).
您还可以在不使用范围的情况下获得所需的结果.试试这个:
4.step(0, -1) do |i|
puts i
end
Run Code Online (Sandbox Code Playgroud)
这将以步长-1从步进4到0.但是,我不知道这是否适用于除Integer参数之外的任何内容.
小智 6
您甚至可以使用for
循环:
for n in 4.downto(0) do
print n
end
Run Code Online (Sandbox Code Playgroud)
打印:
4
3
2
1
0
Run Code Online (Sandbox Code Playgroud)