我并不是说Array
-> |value,index|
和Hash
-> |key,value|
不是疯子(请参阅Horace Loeb的评论),但我是说有一种理智地期待这种安排的方法。
当我处理数组时,我专注于数组中的元素(而不是索引,因为索引是暂时的)。该方法是每个带有索引的,即每个+索引,或| each,index |或|value,index|
。这也与将索引视为可选参数(例如| value |)相一致。等于| value,index = nil | 与| value,index |一致。
在处理散列时,我通常更关注键而不是值,并且通常按key => value
或顺序处理键和值hash[key] = value
。
如果您想进行鸭式打字,则可以显式地使用Brent Longborough显示的已定义方法,或显式使用maxhawkins的隐式方法。
Ruby只是为了使语言适合程序员,而不是为了使程序员适应语言。这就是为什么有很多方法的原因。思考事物的方法有很多。在Ruby中,您选择最接近的代码,其余代码通常非常简洁明了。
对于最初的问题,“在Ruby中迭代遍历数组的“正确”方法是什么?”,我认为核心方法(即没有强大的语法糖或面向对象的能力)是:
for index in 0 ... array.size
puts "array[#{index}] = #{array[index].inspect}"
end
但是Ruby只是关于强大的语法糖和面向对象的功能,但是无论如何,这里的哈希值是等效的,并且可以对键进行排序:
for key in hash.keys.sort
puts "hash[#{key.inspect}] = #{hash[key].inspect}"
end
因此,我的回答是,“在Ruby中迭代数组的“正确”方法取决于您(即程序员或编程团队)和项目。” 更好的Ruby程序员会做出更好的选择(选择哪种语法功能和/或哪种面向对象的方法)。更好的Ruby程序员继续寻找更多方法。
现在,我想问另一个问题,“在Ruby中向后遍历Range的“正确”方法是什么?”!(这个问题是我来到此页面的方式。)
很好(对于前锋):
(1..10).each{|i| puts "i=#{i}" }
但我不喜欢这样做(为了倒退):
(1..10).to_a.reverse.each{|i| puts "i=#{i}" }
好吧,我实际上并不介意做太多事情,但是当我在向后教学时,我想向我的学生展示一个很好的对称性(即,差异最小,例如仅添加一个反向符号或步骤-1,但没有修改其他内容)。您可以(为了对称):
(a=*1..10).each{|i| puts "i=#{i}" }
和
(a=*1..10).reverse.each{|i| puts "i=#{i}" }
我不太喜欢,但是你做不到
(*1..10).each{|i| puts "i=#{i}" }
(*1..10).reverse.each{|i| puts "i=#{i}" }
#
(1..10).step(1){|i| puts "i=#{i}" }
(1..10).step(-1){|i| puts "i=#{i}" }
#
(1..10).each{|i| puts "i=#{i}" }
(10..1).each{|i| puts "i=#{i}" } # I don't want this though. It's dangerous
你最终可以做
class Range
def each_reverse(&block)
self.to_a.reverse.each(&block)
end
end
但是我想教纯粹的Ruby而不是面向对象的方法(到目前为止)。我想向后迭代:
- 不创建数组(考虑0..1000000000)
- 适用于任何范围(例如,字符串,而不仅仅是整数)
- 无需使用任何额外的面向对象的功能(即不进行类修改)
我相信,如果没有定义pred
方法,这是不可能的,这意味着修改Range类以使用它。如果可以的话,请告诉我,否则,尽管可能会令人失望,但对确认不可能的确认将不胜感激。也许Ruby 1.9解决了这个问题。
(感谢您花时间阅读本文。)
array#each_with_index
的用途|value, key|
,因为该方法顾名思义订单,而用于为了hash#each
模仿hash[key] = value
语法?