Объединяйте общие ключи в хэш-строку - PullRequest
7 голосов
/ 09 июня 2011

У меня есть этот массив пар:

[{"a"=>"1"}, {"b"=>"2"}, {"a"=>"3"}, {"b"=>"4"}, {"a"=>"5"}]

Я хотел бы, чтобы метод объединял общие ключи с несколькими значениями в:

[{"a"=>["1","3","5"]}, {"b"=>["2","4"]}]

Ответы [ 5 ]

4 голосов
/ 09 июня 2011

Улучшено по предложению Марка-Андре.

array = [{"a"=>"1"}, {"b"=>"2"}, {"a"=>"3"}, {"b"=>"4"}, {"a"=>"5"}]
array.group_by(&:keys).map{|k, v| {k.first => v.flat_map(&:values)}}

Или

array.group_by{|h| h.keys.first}.each_value{|a| a.map!{|h| h.values.first}}
1 голос
/ 09 июня 2011

Решение вашей проблемы:

array.map(&:first).group_by(&:first).map{|k, v| {k => v.map(&:last)}}

Мне интересно, почему вы начинаете и заканчиваете хешами, содержащими только одну пару ключей.Массивы были бы лучше подходят.Например:

other = [["a", "1"], ["b", "2"], ["a", "3"], ["b", "4"], ["a", "5"]]
r = other.group_by(&:first).map{|k, v| [k => v.map(&:last)]}
r  # => [["a", ["1", "3", "5"]], ["b", ["2", "4"]]]
Hash[r] # => {"a"=>["1", "3", "5"], "b"=>["2", "4"]}
1 голос
/ 09 июня 2011

Еще не пробовал, но что-то подобное также должно работать

   a.each_with_object( Hash.new{ |h,k| h[k] = [] } ) do |x, hash|
      hash[x.keys.first] << x.values.first
   end

edit: для одного вкладыша и того же вывода:

[a.each_with_object( Hash.new{ |h,k| h[k] = [] } ) { |x, hash| hash[x.keys.first] << x.values.first }]
0 голосов
/ 25 декабря 2012

Не уверен, что вы даете награды за краткость, но мне нравится этот способ.Для этого идеально подходит функция объединения с блоком:

new = {}
array.each {|p| new.merge!(p) {|k,l,r| [l,r].flatten }}
0 голосов
/ 09 июня 2011
array = [{"a"=>"1"}, {"b"=>"2"}, {"a"=>"3"}, {"b"=>"4"}, {"a"=>"5"}]
{}.tap{ |r| array.each{ |h| h.each{ |k,v| (r[k]||=[]) << v } } }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...