Объединить массив хэшей по паре ключ-значение - PullRequest
0 голосов
/ 27 сентября 2018

У меня есть массив хэшей следующим образом:

[
  {'abc_id'=>'1234', 'def_id'=>[]},
  {'abc_id'=>'5678', 'def_id'=>['11', '22']},
  {'abc_id'=>'1234', 'def_id'=>['33', '44']},
  {'abc_id'=>'5678', 'def_id'=>['55', '66']}
]

Я пытаюсь объединить несколько хешей с одной и той же парой ключ-значение в один хеш.Таким образом, у нас есть две пары с одинаковым значением для клавиши 'abc_id' следующим образом:

  • {'abc_id'=>'1234', 'def_id'=>[]} и {'abc_id'=>'1234', 'def_id'=>['33', '44']}
  • {'abc_id'=>'5678', 'def_id'=>['11', '22']} и {'abc_id'=>'5678', 'def_id'=>['55', '66']}

Я ожидаю объединения нескольких хэшей с одинаковыми парами ключ-значение в один отдельный хеш.Для двух вышеуказанных пар они должны быть соответственно:

  • {'abc_id'=>'1234', 'def_id'=>['33', '44']}
  • {'abc_id'=>'5678', 'def_id'=>['11', '22', '55', '66']}

Ответы [ 3 ]

0 голосов
/ 27 сентября 2018

Еще один вариант:

array
  .map.with_object({}) { |h, hh| hh[h['abc_id']].nil? ? hh[h['abc_id']] = h['def_id'] : hh[h['abc_id']] += h['def_id'] }
  .map{ |k, v| {'abc_id' => k, 'def_id' => v} }

Первая часть возвращает

# {"1234"=>["33", "44"], "5678"=>["11", "22", "55", "66"]}

Вторая часть восстанавливает исходную структуру, возвращая:

#=> [{"abc_id"=>"1234", "def_id"=>["33", "44"]}, {"abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"]}]
0 голосов
/ 27 сентября 2018

Можно использовать форму Hash # update (он же merge!) и Hash # merge , который использует блок для определения значений ключей, присутствующих в обоих хешахбыть объединеннымЗдесь это должно быть сделано на двух уровнях.

Позволяя arr быть массивом, данным в вопросе, эти методы используются следующим образом.

arr.each_with_object({}) do |g,h|
  h.update(g['abc_id']=>g) do |_,o,n|
    o.merge(n) { |k,oo,nn| k=='def_id' ? oo+nn : oo }
  end
end.values
  #=> [{"abc_id"=>"1234", "def_id"=>["33", "44"]},
  #    {"abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"]}]

См. Документацию для объясненияпеременных блока _, o, n, k, oo и nn.Я использовал подчеркивание для представления общего ключа с update, чтобы сообщить читателю, что он не используется в расчете блока.

Обратите внимание, что получатель Hash # values ​​ следующий.

{ "1234"=>{ "abc_id"=>"1234", "def_id"=>["33", "44"] },
  "5678"=>{ "abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"] } }
0 голосов
/ 27 сентября 2018

Более-менее общий и расширяемый вариант будет:

input.
  group_by { |h| h['abc_id'] }.
  map do |k, v|
    v.reduce do |acc, arr|
      #  use `+` instead of `|` to save duplicates  ⇓⇓⇓
      acc.merge(arr) { |_, v1, v2| Array === v1 ? v1 | v2 : v1 }
    end
  end
#⇒ [{"abc_id"=>"1234", "def_id"=>["33", "44"]},
#   {"abc_id"=>"5678", "def_id"=>["11", "22", "55", "66"]}]
...