2012-06-08 31 views
54

Ví dụ, tôi có mảng băm đơnMảng băm để băm

a = [{a: :b}, {c: :d}] 

Cách tốt nhất để chuyển đổi nó thành này là gì?

{a: :b, c: :d} 

Trả lời

94

Bạn có thể sử dụng

a.reduce Hash.new, :merge 

mà trực tiếp mang lại

{:a=>:b, :c=>:d} 

Lưu ý rằng trong trường hợp va chạm thứ tự là quan trọng. băm sau ghi đè lên các ánh xạ trước, xem ví dụ:

[{a: :b}, {c: :d}, {e: :f, a: :g}].reduce Hash.new, :merge # {:a=>:g, :c=>:d, :e=>:f} 
+25

'Hash.new', hoặc như những người bạn thích gọi anh ta, '{}' :-) Vì vậy, nhiều như tôi thích giải pháp chức năng tinh khiết, lưu ý rằng 'hợp nhất' sẽ tạo ra một băm mới trên mỗi lần lặp; chúng ta có thể sử dụng 'update' thay vào đó (nó sẽ không gây rối với hash đầu vào, đó là điểm quan trọng):' hs.reduce ({},: update) ' – tokland

+0

Đẹp được thực hiện – Aeramor

+0

@tokland, đăng bình luận của bạn dưới dạng riêng biệt câu trả lời - nó sẽ hiển thị nhiều hơn – Jason

19

Hai dòng này là tương đương:

total_hash = hs.reduce({}) { |acc_hash, hash| acc_hash.merge(hash) } 
total_hash = hs.reduce({}, :merge) 

Lưu ý rằng Hash#merge tạo một hash mới trên mỗi lần lặp, có thể là một vấn đề nếu bạn đang xây dựng một băm lớn. Trong trường hợp đó, sử dụng update thay vì:

total_hash = hs.reduce({}, :update) 

Một cách tiếp cận thay thế sẽ được chuyển đổi băm để cặp và sau đó xây dựng băm thức:

total_hash = hs.flat_map(&:to_a).to_h 
18

Bạn có thể sử dụng .inject:

a.inject(:merge) 
#=> {:a=>:b, :c=>:d} 

Demonstration

Mà bắt đầu một băm mới trên mỗi lần lặp từ hai hợp nhất. Để tránh điều này, bạn có thể sử dụng phá hoại :merge! (hoặc :update, mà là như nhau):

a.inject(:merge!) 
#=> {:a=>:b, :c=>:d} 

Demonstration

0

Hãy thử điều này

a.inject({}){|acc, hash| acc.merge(hash)} #=> {:a=>:b, :c=>:d} 
Các vấn đề liên quan