Karma dizisini tek karma üzerine eşleyen raylar


94

Bunun gibi bir dizi karmaşam var:

 [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]

Ve bunu şöyle tek bir hash üzerine eşlemeye çalışıyorum:

{"testPARAM2"=>"testVAL2", "testPARAM1"=>"testVAL1"}

Kullanarak başardım

  par={}
  mitem["params"].each { |h| h.each {|k,v| par[k]=v} } 

Ama bunu daha deyimsel bir şekilde yapmanın mümkün olup olmadığını merak ediyordum (tercihen yerel bir değişken kullanmadan).

Bunu nasıl yapabilirim?

Yanıtlar:


164

İstediğinizi besteleyebilir Enumerable#reduceve Hash#mergebaşarabilirsiniz.

input = [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]
input.reduce({}, :merge)
  is {"testPARAM2"=>"testVAL2", "testPARAM1"=>"testVAL1"}

Bir diziyi, her bir elemanı arasına bir yöntem çağrısı yapıştırmaya benzer bir şekilde azaltmak.

Örneğin [1, 2, 3].reduce(0, :+)söylemek 0 + 1 + 2 + 3ve vermek gibidir 6.

Bizim durumumuzda benzer bir şey yapıyoruz, ancak iki hash'ı birleştiren birleştirme işlevi ile.

[{:a => 1}, {:b => 2}, {:c => 3}].reduce({}, :merge)
  is {}.merge({:a => 1}.merge({:b => 2}.merge({:c => 3})))
  is {:a => 1, :b => 2, :c => 3}

1
Teşekkürler, bu harika bir cevap :) Çok güzel açıklandı!
Bart Platak

42
input.reduce (&: merge) yeterlidir.
redgetan

@redgetan'dan farklı input.reduce(:merge)mı?
David van Geest

1
@David van Geest: Bu durumda eşdeğerdirler. Burada kullanılan tekli ve işareti, sembolden bir blok oluşturur. Ancak, azaltmanın bir sembolü kabul eden özel bir durumu vardır. Örneği basitleştirmek için tekli ampersan operatöründen kaçınmak istedim, ancak redgetan bu durumda başlangıç ​​değerinin isteğe bağlı olduğu konusunda doğru.
cjhveal

1
Onun merge!yerine kullanırsanız merge, ilk karmayı değiştireceğinizi (ki bunu istemeyebilirsiniz) ancak her yeni birleştirme için bir ara karma oluşturmayacağınızı unutmayın.
Phrogz

51

Peki ya:

h = [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]
r = h.inject(:merge)

Bu şema, Joshua'nın yanıtladığı ile etkili bir şekilde aynıdır, ancak tüm karmalara #merge (yöntem adı bir sembol olarak aktarılır) tekrar tekrar uygulanır (enjekte etmeyi, öğeler arasında bir operatör enjekte etmek olarak düşünün). # Enjekte bölümüne bakın .
shigeya

2
Neden h.inject (&: merge) 'de olduğu gibi ve işaretine ihtiyacımız yok?
Donato

5
Çünkü inject yöntemi, bir sembolü, yöntem adı olarak da yorumlanacak bir parametre olarak kabul eder. Enjeksiyonun özelliği.
shigeya

9

#İnject kullanın

hashes = [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]
merged = hashes.inject({}) { |aggregate, hash| aggregate.merge hash }
merged # => {"testPARAM1"=>"testVAL1", "testPARAM2"=>"testVAL2"}

0

Burada , her ikisi de birbirinin takma adı olduğundan , Enumerable sınıfından enjekte veya azaltmayı kullanabilirsiniz , bu nedenle ikisinin de performans avantajı yoktur.

 sample = [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]

 result1 = sample.reduce(:merge)
 # {"testPARAM1"=>"testVAL1", "testPARAM2"=>"testVAL2"}

 result2 = sample.inject(:merge)
 # {"testPARAM1"=>"testVAL1", "testPARAM2"=>"testVAL2"}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.