Как добавить суммы на группу в двумерном массиве с помощью перечислимых функций? - PullRequest
1 голос
/ 23 марта 2019

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

ary = [["a", 10],["a", 20],["b", 9],["b",7],["c",12]]

Я хочу суммировать числовые значения одним и тем же ключом, создавая хеш-код:

desired_result = {"a"=>30, "b"=>16, "c"=>12}

Я могу использовать хеш со значением по умолчанию (0) и циклом следующим образом:

rslt = Hash.new(0)
ary.each do |line|
  rslt[line[0]] += line[1]
end

Но я хочу избежать цикла и использовать функции перечисления. Я придумал следующее (довольно некрасивое) выражение:

rslt = ary.group_by {|a| a[0]}.map {|k,v| [k, v.map {|v| v[1]}.reduce(:+)]}.to_h

, который гораздо сложнее читать, чем loop-версию.

Есть ли способ сделать это более элегантно без цикла?

Ответы [ 4 ]

3 голосов
/ 23 марта 2019

Вы можете использовать each_with_object (или inject) и передать хеш, где новые ключи инициализируются со значением ноль:

ary.each_with_object(Hash.new(0)){ |(k, v), count| count[k] += v }
# => {"a"=>30, "b"=>16, "c"=>12}
2 голосов
/ 24 марта 2019

После Enumerable # group_by Я бы предложил объединить в цепочку Hash # transform_values ​​:

ary.group_by(&:first).transform_values { |v| v.sum(&:last) }
#=> {"a"=>30, "b"=>16, "c"=>12}
1 голос
/ 23 марта 2019
ary.group_by(&:first).map {|k, v| [k, v.sum(&:last)]}.to_h
1 голос
/ 23 марта 2019
ary = [["a", 10],["a", 20],["b", 9],["b",7],["c",12]]

h=ary.group_by{|x|x[0]}.each_with_object({}) do |(k,v),h|
  h[k]=v.sum{|y|y[1]}
end

тел

{"a"=>30, "b"=>16, "c"=>12}
...