Esiste un modo semplice o elegante per unire due hash senza sovrascrivere chiavi duplicate?
Cioè, se la chiave è presente nell'hash originale non voglio cambiarne il valore.
Esiste un modo semplice o elegante per unire due hash senza sovrascrivere chiavi duplicate?
Cioè, se la chiave è presente nell'hash originale non voglio cambiarne il valore.
Risposte:
Se si dispone di due hash, options
e defaults
, e si desidera unire defaults
in options
senza sovrascrivere le chiavi esistenti, ciò che si vuole veramente fare è il contrario: si fondono options
in defaults
:
options = defaults.merge(options)
Oppure, se stai usando Rails puoi fare:
options.reverse_merge!(defaults)
reverse_merge!
causa di problemi di sicurezza nelle rotaie 5.1
Se il tuo problema è che l'hash originale e la seconda potrebbero avere chiavi duplicate e non vuoi sovrascrivere in nessuna delle due direzioni, potresti dover eseguire una semplice fusione manuale con una sorta di controllo e gestione delle collisioni:
hash2.each_key do |key|
if ( hash1.has_key?(key) )
hash1[ "hash2-originated-#{key}" ] = hash2[key]
else
hash1[key]=hash2[key]
end
end
Ovviamente, questo è molto rudimentale e presuppone che l'hash1 non abbia chiavi chiamate "hash2-origated-qualunque" - potresti stare meglio semplicemente aggiungendo un numero alla chiave in modo che diventi key1, key2 e così via fino a quando non premi uno che non è già in hash1. Inoltre, non ho fatto alcun rubino per alcuni mesi, quindi probabilmente non è sintatticamente corretto, ma dovresti essere in grado di ottenere l'essenza.
In alternativa, ridefinire il valore della chiave come un array in modo che hash1 [chiave] restituisca il valore originale da hash1 e il valore da hash2. Dipende da cosa vuoi che il tuo risultato sia davvero.
Qui puoi unire i tuoi 2 hash di 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 }
Se vuoi unire i due hash options
e defaults
senza sovrascrivere l'hash di destinazione, puoi verificare select
se la chiave è già presente nell'hash di destinazione. Ecco la pura soluzione Ruby senza Rails:
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}
O se la chiave è presente, ma contiene nil
e si desidera sovrascriverla:
options.merge!(defaults.select{ |k,_| options[k].nil? })