Ruby에서 중복 키를 덮어 쓰지 않고 두 개의 해시를 병합하려면 어떻게해야합니까?


140

중복 키를 덮어 쓰지 않고 두 개의 해시를 병합 하는 쉽고 우아한 방법이 있습니까?

즉, 키가 원래 해시에 있으면 값을 변경하고 싶지 않습니다.


실제로 배열 (예 : [ 'a', 'b', 'c']) 또는 해시 (예 : { 'a'=> 1, 'b'=> 2, 'c'=> 3})를 의미합니까? ?
Alex Reisner

미안 해요 :) 해시에 대해 얘기했다
클라우디오 Acciaresi

답변:


232

두 해시를 가지고있는 경우 optionsdefaults,와 병합 할 defaultsoptions병합 : 기존 키를 덮어 쓰지 않고, 당신이 정말로 원하는 것은 반대입니다 options로는 defaults:

options = defaults.merge(options)

또는 Rails를 사용하는 경우 다음을 수행 할 수 있습니다.

options.reverse_merge!(defaults)

reverse_merge에 대해 대단히 감사합니다! 방법 : 그것을 알고하지 않았다
클라우디오 Acciaresi에게

괄호가 필요한 이유는 무엇입니까? default.merge 옵션이 표시되지 않습니다.
Donato

1
reverse_merge!레일의 보안 문제로 인해 더 이상 사용되지 않습니다 5.1
Mirv-Matt

@ Mirv-Matt-감가 상각 통지가 표시되지 않습니다. apidock.com/rails/v6.0.0/Hash/reverse_merge%21
Kshitij

17

표준 Ruby 라이브러리에는 기존 값을 덮어 쓰거나 해시를 다시 할당하지 않고 해시를 병합하는 방법이 있습니다.

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

3

문제가 원래 해시와 두 번째 해시 모두 중복 키를 가지고 있고 어느 방향으로도 덮어 쓰지 않으려는 경우 충돌 검사 및 처리와 간단한 수동 병합을 수행해야 할 수도 있습니다.

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

분명히 이것은 매우 기초적이며 hash1에는 "hash2-originated-whatever"라는 키가 없다고 가정합니다. 키에 숫자를 추가하는 것이 더 좋을 수 있으므로 키를 누를 때까지 키 1, 키 2 등이됩니다. 아직 hash1에없는 것. 또한, 나는 몇 달 동안 루비를하지 않았으므로 구문 적으로 정확하지는 않지만 요점을 얻을 수 있어야합니다.

또는 hash1 [key]가 hash1의 원래 값과 hash2의 값을 리턴하도록 키 값을 배열로 재정의하십시오. 당신이 원하는 결과에 따라 달라집니다.


두 키를 유지하지 않고 동일한 키의 값을 합산하면 어떨까요?
Tom KC Chiu

1
@ TomK.C.Chiu 그것은 우리가 질문에서 판단 할 수없는 상황에 따라 크게 달라질 것입니다-hash1의 값이 문자열이고 hash2의 값이 정수라면? 경우에 따라 실행 가능한 옵션 일 수도 있지만 더 자주 문제가 발생할 수 있습니다. 값에 대한 목록 사용에 대한 제안은이 문제를 매우 명확하게 해결합니다.
glenatron

0

여기에서 2 해시를 병합 할 수 있습니다 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

당신이 두 개의 해시 병합 할 경우 optionsdefaults대상 해시를 덮어 쓰지 않고를, 당신은 확인 할 수 있습니다 select키가 이미 대상 해시에있는 경우. Rails가없는 순수한 Ruby 솔루션은 다음과 같습니다.

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}

또는 키가 있지만 포함되어 nil있고 덮어 쓰려는 경우 :

options.merge!(defaults.select{ |k,_| options[k].nil? })
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.