Как я могу объединить два хэша без перезаписанных дубликатов ключей в Ruby?

Есть ли простой или элегантный способ слияния двух хэшей без перезаписи дубликатов ключей?

То есть, если ключ присутствует в исходном хеше, я не хочу изменять его значение.

Ответ 1

Если у вас есть две хэши, options и defaults, и вы хотите объединить defaults в options без перезаписи существующих ключей, то вы действительно хотите сделать обратное: merge options в defaults:

options = defaults.merge(options)

Или, если вы используете Rails, вы можете сделать:

options.reverse_merge!(defaults)

Ответ 2

В стандартной библиотеке 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-origininated-whatever" - вам может быть лучше просто добавить номер к ключу, чтобы он стал key1, key2 и так далее, пока вы нажмете на тот, который еще не находится в hash1. Кроме того, я не делал никакого рубина в течение нескольких месяцев, чтобы, вероятно, не синтаксически исправлять, но вы должны иметь возможность получить суть.

Альтернативно переопределить значение ключа как массива, чтобы hash1 [key] возвращал исходное значение из hash1 и значение из hash2. Зависит от того, что вы хотите, чтобы ваш результат был действительно.

Ответ 4

Здесь вы можете объединить 2 хеша с помощью reverse_merge

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

user = {
  name: 'Jhon Doe',
  email: '[email protected]' 
}
newHash = oder.reverse_merge!(user)
render json: { data: newHash, status: 200 }