Existe uma maneira fácil ou elegante de mesclar dois hashes sem substituir chaves duplicadas?
Ou seja, se a chave estiver presente no hash original, não quero alterar seu valor.
Existe uma maneira fácil ou elegante de mesclar dois hashes sem substituir chaves duplicadas?
Ou seja, se a chave estiver presente no hash original, não quero alterar seu valor.
Respostas:
Se você possui dois hashes options
e defaults
deseja unir defaults
-se options
sem substituir as chaves existentes, o que realmente deseja fazer é o inverso: unir options
- se a defaults
:
options = defaults.merge(options)
Ou, se você estiver usando o Rails, poderá:
options.reverse_merge!(defaults)
reverse_merge!
por questões de segurança em trilhos 5.1
Se o seu problema é que o hash original e o segundo podem ter chaves duplicadas e você não deseja sobrescrever em nenhuma direção, pode ser necessário fazer uma mesclagem manual simples com algum tipo de verificação e manuseio de colisão:
hash2.each_key do |key|
if ( hash1.has_key?(key) )
hash1[ "hash2-originated-#{key}" ] = hash2[key]
else
hash1[key]=hash2[key]
end
end
Obviamente, isso é muito rudimentar e supõe que o hash1 não possui nenhuma chave chamada "hash2-originou-seja o que for" - é melhor adicionar um número à chave para que ela se torne key1, key2 etc. um que ainda não esteja no hash1. Além disso, há alguns meses que não faço ruby, então isso provavelmente não está sintaticamente correto, mas você deve ser capaz de entender.
Como alternativa, redefina o valor da chave como uma matriz para que o hash1 [chave] retorne o valor original do hash1 e o valor do hash2. Depende do que você quer que seu resultado seja realmente.
Aqui você pode mesclar seu hash 2 por 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 você deseja mesclar os dois hashes options
e defaults
sem substituir o hash de destino, verifique select
se a chave já está presente no hash de destino. Aqui está a solução Ruby pura sem 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}
Ou, se a chave estiver presente, mas contiver nil
e você quiser substituí-la:
options.merge!(defaults.select{ |k,_| options[k].nil? })