Làm thế nào để có được một đầu ra cụ thể lặp lại một hàm băm trong Ruby?


218

Tôi muốn nhận được một đầu ra cụ thể lặp lại một Ruby Hash.

Đây là Hash tôi muốn lặp lại:

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

Đây là đầu ra tôi muốn nhận:

1-----

a

b

2-----

c

3-----

d 

e

f

g

4-----

h

Trong Ruby, làm cách nào tôi có thể nhận được đầu ra như vậy với Hash của mình?


3
Nếu bạn đang lặp lại một hàm băm và mong muốn nó được đặt hàng, có lẽ bạn cần sử dụng một số loại bộ sưu tập khác
Allen Rice

Tôi có thể vượt qua các giá trị băm như tùy chọn nút radio không ??
sts

đang vượt qua hàm băm dưới dạng tùy chọn nút radio .. nhưng đối với tùy chọn đầu tiên là nhận nút radio, đối với các giá trị khác thì không nhận được.
sts

1
@ ALLen: Băm được đặt hàng trong Ruby 1.9. Rails cũng cung cấp một OrderedHash (nó chỉ sử dụng một cách tiết kiệm) nếu bạn sử dụng Ruby <1.9. Xem Culann.com/2008/01/rails-goodies-activesupportorderedhash
James A. Rosen

Câu trả lời:


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

Về thứ tự tôi nên thêm, rằng trong 1.8, các mục sẽ được lặp theo thứ tự ngẫu nhiên (thực ra, theo thứ tự được xác định bởi hàm băm của Fixnum), trong khi ở 1.9, nó sẽ được lặp theo thứ tự chữ.


1
Ở đây, nếu khóa không được sử dụng ở bất cứ đâu? . chúng ta cần phải đặt một ?vị trí quan trọng? ví dụ: |?, array|đây có phải là cú pháp hợp lệ không?
huzefa biyawarwala

1
@huzefabiyawarwala Không, ?không phải là tên biến hợp lệ trong Ruby. Bạn có thể sử dụng _, nhưng bạn không cần .
sepp2k

2
@huzefabiyawarwala Vâng, bạn có thể viết|_, v|
sepp2k

1
Điều gì sử dụng mảng tên biến thay vì v hoặc giá trị?
jrhicks

1
@jrhicks Vì OP có hàm băm có giá trị là mảng.
Radon Rosborough

85

Cách cơ bản nhất để lặp lại hàm băm như sau:

hash.each do |key, value|
  puts key
  puts value
end

Vâng, điều này có ý nghĩa. Tại sao câu trả lời của @ sepp2k có # {} trên khóa?
committedandroider

Ồ, đừng bận tâm. Tôi thấy rằng nó đã được cho chuỗi suy
committedandroider

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

18

Gọi sort trên hàm băm chuyển đổi nó thành các mảng lồng nhau và sau đó sắp xếp chúng theo khóa, vì vậy tất cả những gì bạn cần là:

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

Và nếu bạn không thực sự cần phần "----", thì đó có thể chỉ là:

puts h.sort

Các khóa băm là số, vì vậy '[k + "----"]' tăng TypeError (Chuỗi không thể bị ép buộc vào Fixnum). Bạn cần '[k.to_s + "----"]'
glenn jackman

Đúng đủ rồi. Tôi đã có thư trong phiên bản thử nghiệm của tôi. Đã sửa lỗi, sử dụng "# {k} ----" tốt hơn nữa.
glenn mcdonald

10

Giải pháp một dòng của tôi:

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

Tôi nghĩ nó khá dễ đọc.


1

Bạn cũng có thể tinh chỉnh Hash::each để nó sẽ hỗ trợ liệt kê đệ quy . Đây là phiên bản Hash::each( Hash::each_pair) của tôi với hỗ trợ chặnliệt kê :

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

Dưới đây là cách sử dụng ví dụ của Hash::eachcó và không có recursivelá cờ:

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

Đây là ví dụ từ chính câu hỏi:

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"]

Ngoài ra hãy xem phiên bản đệ quy của tôi Hash::merge( Hash::merge!) tại đây .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.