Ruby'de yinelenen anahtarların üzerine yazmadan iki karmayı nasıl birleştirebilirim?


141

Yinelenen anahtarların üzerine yazmadan iki karmayı birleştirmenin kolay veya zarif bir yolu var mı ?

Yani, anahtar orijinal karmada varsa, değerini değiştirmek istemiyorum.


Gerçekten dizileri mi kastediyorsunuz (örneğin: ['a', 'b', 'c']) veya karmaları (örneğin: {'a' => 1, 'b' => 2, 'c' => 3}) ?
Alex Reisner

Üzgünüm, karma hakkında konuşuyordum :)
Claudio Acciaresi

Yanıtlar:


233

İki karmaları var ise optionsve defaultsve Birleştirmek istediğiniz defaultsiçine optionsbirleştirme: Mevcut anahtarları üzerine yazmadan, ne gerçekten yapmak istiyorum tersidir optionsiçine defaults:

options = defaults.merge(options)

Veya Rails kullanıyorsanız şunları yapabilirsiniz:

options.reverse_merge!(defaults)

Tamamen katılıyorum, reverse_merge için çok teşekkürler! yöntem bilmiyordum :)
Claudio Acciaresi

Burada parantezlere neden ihtiyaç var? Sadece varsayılan yapamazsınız. Birleştirme seçenekleri görünür.
Donato

1
reverse_merge!5.1
Mirv - Matt

1
@ Mirv-Matt - Bir amortisman notu görmüyorum. apidock.com/rails/v6.0.0/Hash/reverse_merge%21
Kshitij

17

Standart Ruby kütüphanesinde, mevcut değerlerin üzerine yazmadan veya karmayı yeniden atamadan Karma'ları birleştirmenin bir yolu vardır.

important_hash.merge!(defaults) { |key, important, default| important }

3

Sorunlarınız orijinal karmanın ve ikincisinin her ikisinin de yinelenen anahtarları olması ve her iki yönde de üzerine yazmak istemiyorsanız, bir tür çarpışma kontrolü ve kullanımı ile basit bir manuel birleştirme için gitmeniz gerekebilir:

hash2.each_key do |key|
  if ( hash1.has_key?(key) )
       hash1[ "hash2-originated-#{key}" ] = hash2[key]
  else
       hash1[key]=hash2[key]
  end
end

Açıkçası, bu çok ilkeldir ve hash1'in "hash2 kaynaklı-ne olursa olsun" adı verilen herhangi bir anahtarı olmadığını varsayar - tuşa bir sayı eklemeniz daha iyi olabilir, bu yüzden tuşa basana kadar tuş1, tuş2 vb. hash1'de olmayan bir tane. Ayrıca, birkaç aydır hiç yakut yapmadım, bu muhtemelen sözdizimsel olarak doğru değil, ama özü elde edebilmelisin.

Alternatif olarak, anahtarın değerini bir dizi olarak yeniden tanımlayın, böylece hash1 [key], hash1'den orijinal değeri ve hash2'den değeri döndürür. Sonucunuzun gerçekten olmasını istediğiniz şeye bağlıdır.


Her iki anahtarı da tutmamaya, ancak aynı anahtarın değerlerini eklemeye ne dersiniz?
Tom KC Chiu

1
@ TomK.C.Chiu Bu, sorudan yargılayamayacağımız koşullara çok bağlı olacaktır - ya hash1'deki değerler dize ve hash2 tamsayı ise? Geçerli bir seçenek olabilecek bazı durumlarda, ancak daha sık sorunlara neden olur - değerler için listelerin kullanılması önerisi oldukça temiz çalışır.
glenatron

0

Burada 2 karma değerini birleştirerek reverse_merge

order = {
 id: 33987,
 platform: 'web'
}

user = {
  name: 'Jhon Doe',
  email: 'jhon.doe@gmail.com' 
}
newHash = oder.reverse_merge!(user)
render json: { data: newHash, status: 200 }

0

İki karmaları birleştirmek istiyorsanız optionsve defaultshedef karma üzerine yazmadan, sen kontrol edebilir selectanahtar zaten hedef karma bulunup bulunmadığının. Rails olmadan saf Ruby çözümü:

options  = { "a" => 100, "b" => 200 }
defaults = { "b" => 254, "c" => 300 }
options.merge!(defaults.select{ |k,_| not options.has_key? k })

# output
# => {"a"=>100, "b"=>200, "c"=>300}

Veya anahtar varsa, ancak içeriyorsa nilve üzerine yazmak istiyorsanız:

options.merge!(defaults.select{ |k,_| options[k].nil? })
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.