Нахождение суммы конкретных значений массива в хэше - PullRequest
1 голос
/ 06 ноября 2019

Вот мой массив:

collection

=> [{:title=>"Movie A", :studio=>"Alpha Films", :worldwide_gross=>10},

{:title=>"Movie B", :studio=>"Alpha Films", :worldwide_gross=>30},

{:title=>"Movie C", :studio=>"Omega Films", :worldwide_gross=>30}]

Моя цель - вернуть сумму каждой соответствующей студии:

#=> :studio => "Alpha Films", :worldwide_gross => 40

#=> :studio => "Omega Films", :worldwide_gross => 30

До сих пор я придумал следующую логику, ноон возвращает только сумму всех студий в одной единовременной сумме:

gross_result = collection.sum {|h| h[:worldwide_gross]}
result #=> 70

Ответы [ 3 ]

1 голос
/ 06 ноября 2019

Вы можете использовать Enumerable#group_by и Hash#transform_values, а затем суммировать, как вы уже сделали:

collection.group_by { |h| h[:studio] }.transform_values { |v| v.sum{ |h| h[:worldwide_gross] } }
#=> {"Alpha Films"=>40, "Omega Films"=>30}

Где group_by возвращает:

collection.group_by { |h| h[:studio] }
#=> {"Alpha Films"=>[{:title=>"Movie A", :studio=>"Alpha Films", :worldwide_gross=>10}, {:title=>"Movie B", :studio=>"Alpha Films", :worldwide_gross=>30}], "Omega Films"=>[{:title=>"Movie C", :studio=>"Omega Films", :worldwide_gross=>30}]}
0 голосов
/ 07 ноября 2019

Вы можете использовать метод уменьшения

result = a.group_by { |h| h[:studio] }.values.map do |arr|
  arr.reduce do |h1, h2|
    h1.merge(h2) do |k, v1, v2|
      k.eql?(:worldwide_gross) ? (v1 + v2) : v1
    end
  end
end

p результат

[{:partner_name=>"company 1", :partner_id=>787, :value=>3}, {:partner_name=>"company 2", :partner_id=>768, :value=>1}, {:partner_name=>"company 3", :partner_id=>769, :value=>1}]
0 голосов
/ 06 ноября 2019

Это решение сначала создает хэш, ключами которого являются уникальные значения g[:studio] для всех хешей g в collection, а значения которого являются суммами g[:worldwide_gross] для всех g для данного ключа. Затем этот хэш преобразуется в нужный хэш.

collection.each_with_object(Hash.new(0)) do |g,h|  
  h[g[:studio]] += g[:worldwide_gross]
end.map { |k,v| { studio: k, worldwide_gross: v } }
  #=> [{:studio=>"Alpha Films", :worldwide_gross=>40},
  #    {:studio=>"Omega Films", :worldwide_gross=>30}] 

Два шага следующие:

h = collection.each_with_object(Hash.new(0)) do |g,h|
  h[g[:studio]] += g[:worldwide_gross]
end
  #=> {"Alpha Films"=>40, "Omega Films"=>30} 
h.map { |k,v| { studio: k, worldwide_gross: v } }
  #=> [{:studio=>"Alpha Films", :worldwide_gross=>40},
  #    {:studio=>"Omega Films", :worldwide_gross=>30}]  

Вычисление h (иногда называемое подсчетом хэша)) использует форму Hash :: new , которая определяет значение по умолчанию (здесь ноль), которое является значением, возвращаемым h[k] для хеша h, так чтоопределяется, когда h не имеет ключа k. Это эквивалентно следующему.

h = collection.each_with_object({}) do |g,h|
  h[g[:studio]] = (h[g[:studio]] || 0) + g[:worldwide_gross]
end

Если h не имеет ключа g[:studio], тогда h[g[:studio]] #=> nil, поэтому h[g[:studio]] || 0 #=> 0. Если h имеет ключ g[:studio] (значение которого не nil или false), тогда h[g[:studio]] || 0 #=> h[g[:studio]].

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