Объединить значения Ruby Hash с тем же ключом - PullRequest
0 голосов
/ 15 мая 2019

Достигается ли это с помощью выбранных клавиш:

Например

h = [
  {a: 1, b: "Hello", c: "Test1"},
  {a: 2, b: "Hey", c: "Test1"},
  {a: 3, b: "Hi", c: "Test2"}
]

Ожидаемый результат

[
  {a: 1, b: "Hello, Hey", c: "Test1"}, # See here, I don't want key 'a' to be merged
  {a: 3, b: "Hi", c: "Test2"}
]

My Try

g = h.group_by{|k| k[:c]}.values
OUTPUT =>
  [
    [
      {:a=>1, :b=>"Hello", :c=>"Test1"},
      {:a=>2, :b=>"Hey", :c=>"Test1"}
    ], [
      {:a=>3, :b=>"Hi", :c=>"Test2"}
    ]
  ]

g.each do |v|
  if v.length > 1
    c = v.reduce({}) do |s, l|
      s.merge(l) { |_, a, b| [a, b].uniq.join(", ") }
    end
  end

  p c #{:a=>"1, 2", :b=>"Hello, Hey", :c=>"Test1"}
end

Итак, я получаю вывод

{:a=>"1, 2", :b=>"Hello, Hey", :c=>"Test1"}

Но мне нужно было

{a: 1, b: "Hello, Hey", c: "Test1"}

ПРИМЕЧАНИЕ: Это всего лишь тестовый массив HASH, который я взял, чтобы задать свой вопрос. Но фактический хэш имеет много ключей. Поэтому, пожалуйста, не отвечайте с ключевыми ответами

Мне нужно менее сложное решение

Ответы [ 3 ]

3 голосов
/ 15 мая 2019

Я не вижу более простой версии вашего кода. Чтобы он полностью работал, вы можете использовать первый аргумент в блоке merge вместо того, чтобы игнорировать его, чтобы различать, когда вам нужно объединить a и b или когда вы просто используете a. Ваша строка становится:

s.merge(l) { |key, a, b| key == :a ? a : [a, b].uniq.join(", ") }
1 голос
/ 16 мая 2019
h.each_with_object({}) do |g,h|
  h.update(g[:c]=>g) { |_,o,n| o.merge(b: "#{o[:b]}, #{n[:b]}") }
end.values
  #=> [{:a=>1, :b=>"Hello, Hey", :c=>"Test1"},
  #    {:a=>3, :b=>"Hi", :c=>"Test2"}] 

Используется форма Hash # update , в которой используется блок (здесь { |_,o,n| o.merge(b: "#{o[:b]}, #{n[:b]}") }) для определения значений ключей, присутствующих в обоих объединяемых хэшах.Первая переменная блока содержит общий ключ.Я использовал подчеркивание для этой переменной, главным образом, чтобы показать читателю, что она не используется в расчете блока.См. Документацию для определения двух других блочных переменных.

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

h.each_with_object({}) do |g,h|
  h.update(g[:c]=>g) { |_,o,n| o.merge(b: "#{o[:b]}, #{n[:b]}") }
end
  #=> { “Test1”=>{:a=>1, :b=>"Hello, Hey", :c=>"Test1"},
  #     “Test2=>{:a=>3, :b=>"Hi", :c=>"Test2"} }
1 голос
/ 15 мая 2019

Возможно, вы можете рассмотреть эту опцию, но я не знаю, является ли она менее сложной:

h.group_by { |h| h[:c] }.values.map { |tmp| tmp[0].merge(*tmp[1..]) { |key, oldval, newval| key == :b ? [oldval, newval].join(' ') : oldval } }
#=> [{:a=>1, :b=>"Hello Hey", :c=>"Test1"}, {:a=>3, :b=>"Hi", :c=>"Test2"}]

Первая часть группирует хэши по :c

h.group_by { |h| h[:c] }.values #=> [[{:a=>1, :b=>"Hello", :c=>"Test1"}, {:a=>2, :b=>"Hey", :c=>"Test1"}], [{:a=>3, :b=>"Hi", :c=>"Test2"}]]

Затем он сопоставляет первые элементы с другими, используя Hash # merge

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...