如何获得特定的输出,在Ruby中迭代哈希?


218

我想得到一个特定的输出,它迭代了一个Ruby Hash。

这是我要遍历的哈希:

hash = {
  1 => ['a', 'b'], 
  2 => ['c'], 
  3 => ['d', 'e', 'f', 'g'], 
  4 => ['h']
}

这是我想要的输出:

1-----

a

b

2-----

c

3-----

d 

e

f

g

4-----

h

在Ruby中,如何通过Hash获得这样的输出?


3
如果您要迭代哈希并希望将其排序,则可能需要使用其他一些集合类型
艾伦·赖斯

我可以将哈希值作为单选按钮选项传递吗?
sts

传递哈希作为单选按钮选项..但第一个选项是获取单选按钮,其他值则没有。
sts

1
@Allen:哈希在Ruby 1.9中排序。如果您使用的是Ruby <1.9,Rails还提供了OrderedHash(仅少量使用)。参见culann.com/2008/01/rails-goodies-activesupportorderedhash
James A. Rosen

Answers:


323
hash.each do |key, array|
  puts "#{key}-----"
  puts array
end

关于顺序,我应该补充一点,在1.8中,各项将以随机顺序进行迭代(好吧,实际上是按照Fixnum的哈希函数定义的顺序进行),而在1.9中,则将按照原义顺序进行迭代。


1
如果钥匙没有在任何地方使用怎么办?。我们需要?放置钥匙吗?例如:|?, array|这是有效的语法吗?
huzefa biyawarwala

1
@huzefabiyawarwala不,?在Ruby中不是有效的变量名。您可以使用_,但不需要
sepp2k

2
@huzefabiyawarwala是的,你可以写|_, v|
sepp2k

1
什么使用变量名数组而不是v或值?
jrhicks

1
@jrhicks因为OP具有一个值为数组的哈希值。
Radon Rosborough


48
hash.keys.sort.each do |key|
  puts "#{key}-----"
  hash[key].each { |val| puts val }
end

18

在哈希上调用sort会将其转换为嵌套数组,然后按键对它们进行排序,因此,您需要做的是:

puts h.sort.map {|k,v| ["#{k}----"] + v}

如果您实际上不需要“ ----”部分,则可以是:

puts h.sort

哈希键是数字,因此'[k +“ ----”]'引发TypeError(无法将String强制转换为Fixnum)。您需要'[[k.to_s +“ ----”]“'
格伦·杰克曼

足够真实。我的测试版本中有字母。已修复,使用更好的“#{k} ----”。
格伦麦当劳


1

您还可以优化 Hash::each,使其支持递归枚举。这是我的Hash::eachHash::each_pair)版本,具有代码枚举器支持:

module HashRecursive
    refine Hash do
        def each(recursive=false, &block)
            if recursive
                Enumerator.new do |yielder|
                    self.map do |key, value|
                        value.each(recursive=true).map{ |key_next, value_next| yielder << [[key, key_next].flatten, value_next] } if value.is_a?(Hash)
                        yielder << [[key], value]
                    end
                end.entries.each(&block)
            else
                super(&block)
            end
        end
        alias_method(:each_pair, :each)
    end
end

using HashRecursive

下面是使用实例Hash::each有和无recursive标志:

hash = {
    :a => {
        :b => {
            :c => 1,
            :d => [2, 3, 4]
        },
        :e => 5
    },
    :f => 6
}

p hash.each, hash.each {}, hash.each.size
# #<Enumerator: {:a=>{:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}, :f=>6}:each>
# {:a=>{:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}, :f=>6}
# 2

p hash.each(true), hash.each(true) {}, hash.each(true).size
# #<Enumerator: [[[:a, :b, :c], 1], [[:a, :b, :d], [2, 3, 4]], [[:a, :b], {:c=>1, :d=>[2, 3, 4]}], [[:a, :e], 5], [[:a], {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}], [[:f], 6]]:each>
# [[[:a, :b, :c], 1], [[:a, :b, :d], [2, 3, 4]], [[:a, :b], {:c=>1, :d=>[2, 3, 4]}], [[:a, :e], 5], [[:a], {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}], [[:f], 6]]
# 6

hash.each do |key, value|
    puts "#{key} => #{value}"
end
# a => {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}
# f => 6

hash.each(true) do |key, value|
    puts "#{key} => #{value}"
end
# [:a, :b, :c] => 1
# [:a, :b, :d] => [2, 3, 4]
# [:a, :b] => {:c=>1, :d=>[2, 3, 4]}
# [:a, :e] => 5
# [:a] => {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}
# [:f] => 6

hash.each_pair(recursive=true) do |key, value|
    puts "#{key} => #{value}" unless value.is_a?(Hash)
end
# [:a, :b, :c] => 1
# [:a, :b, :d] => [2, 3, 4]
# [:a, :e] => 5
# [:f] => 6

这是问题本身的示例:

hash = {
    1   =>  ["a", "b"], 
    2   =>  ["c"], 
    3   =>  ["a", "d", "f", "g"], 
    4   =>  ["q"]
}

hash.each(recursive=false) do |key, value|
    puts "#{key} => #{value}"
end
# 1 => ["a", "b"]
# 2 => ["c"]
# 3 => ["a", "d", "f", "g"]
# 4 => ["q"]

另外在这里查看我的Hash::mergeHash::merge!)的递归版本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.