PHP尽管有缺点,但在这方面做得很好。数组和哈希之间没有区别(也许我很天真,但这对我来说显然是正确的),要遍历其中任何一个,你都可以这样做
foreach (array/hash as $key => $value)
在Ruby中,有很多方法可以做到这一点:
array.length.times do |i|
end
array.each
array.each_index
for i in array
哈希更有意义,因为我总是用
hash.each do |key, value|
为什么我不能对数组这样做?如果我只想记住一个方法,我想我可以使用each_index(因为它使索引和值都可用),但是必须使用array[index]而不是value是很烦人的。
哦,对了,我忘了array。each_with_index。然而,这个很糟糕,因为它是|值,键|和哈希。每个键|,值|!这不是很疯狂吗?
这将遍历所有元素:
array = [1, 2, 3, 4, 5, 6]
array.each { |x| puts x }
# Output:
1
2
3
4
5
6
这将遍历所有给你值和索引的元素:
array = ["A", "B", "C"]
array.each_with_index {|val, index| puts "#{val} => #{index}" }
# Output:
A => 0
B => 1
C => 2
从你的问题我不太确定你在找哪一个。
如果使用可枚举的mixin(如Rails所做的那样),则可以执行与列出的php代码片段类似的操作。只需使用each_slice方法并将散列平铺。
require 'enumerator'
['a',1,'b',2].to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }
# is equivalent to...
{'a'=>1,'b'=>2}.to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }
更少的猴子补丁需要。
但是,当您有一个递归数组或数组值的散列时,这确实会导致问题。在ruby 1.9中,这个问题通过flatten方法的参数来解决,该方法指定递归的深度。
# Ruby 1.8
[1,2,[1,2,3]].flatten
=> [1,2,1,2,3]
# Ruby 1.9
[1,2,[1,2,3]].flatten(0)
=> [1,2,[1,2,3]]
至于这是否是代码气味的问题,我不确定。通常当我不得不竭尽全力迭代某些内容时,我就会后退一步,意识到我在错误地处理问题。
使用相同的方法迭代数组和散列是有意义的,例如处理嵌套的散列和数组结构,通常由解析器产生,读取JSON文件等。
一个尚未被提及的聪明方法是如何在标准库扩展的Ruby Facets库中实现它。从这里开始:
class Array
# Iterate over index and value. The intention of this
# method is to provide polymorphism with Hash.
#
def each_pair #:yield:
each_with_index {|e, i| yield(i,e) }
end
end
已经有哈希#each_pair,哈希#each的别名。所以在这个补丁之后,我们也有了数组#each_pair,并且可以互换地使用它来遍历哈希和数组。这修复了OP观察到的array# each_with_index与Hash#each相比块参数颠倒的疯狂。使用示例:
my_array = ['Hello', 'World', '!']
my_array.each_pair { |key, value| pp "#{key}, #{value}" }
# result:
"0, Hello"
"1, World"
"2, !"
my_hash = { '0' => 'Hello', '1' => 'World', '2' => '!' }
my_hash.each_pair { |key, value| pp "#{key}, #{value}" }
# result:
"0, Hello"
"1, World"
"2, !"