Как найти сумму на основе ключа типа и имени в ruby? (массив хэшей ruby)

#ruby-on-rails #ruby #ruby-on-rails-5

Вопрос:

Как найти сумму на основе ключа типа и имени в ruby? (массив хэшей ruby)

 eatables = [{type: "fruit", name: "apple", count: 2},
            {type: "vegetable", name: "pumpkin", count: 3},
            {type: 'fruit', name: 'apple', count: 1},
            {type: "vegetable", name: "pumpkin", count: 2}]
 

Желаемый Результат

 [{type: "fruit", name: "apple", count: 3},
 {type: "vegetable", name: "pumpkin", count: 5}]
 

Ответ №1:

 eatables.group_by { |h| h.slice(:name, :type) }
        .map { |key, grouped| key.merge(count: grouped.sum{ |h| h[:count] }) }
 

Первая операция разбивает массив на группы в зависимости от имени и типа.

 {{:name=>"apple", :type=>"fruit"}=>[{:type=>"fruit", :name=>"apple", :count=>2}, {:type=>"fruit", :name=>"apple", :count=>1}], {:name=>"pumpkin", :type=>"vegetable"}=>[{:type=>"vegetable", :name=>"pumpkin", :count=>3}, {:type=>"vegetable", :name=>"pumpkin", :count=>2}]}
 

Затем мы сопоставляем этот хэш и возвращаем массив хэшей с типом, именем и суммой, которые выводят:

 => [{:name=>"apple", :type=>"fruit", :count=>3}, {:name=>"pumpkin", :type=>"vegetable", :count=>5}]
 

Ответ №2:

 eatables.inject(Hash.new(0)) { |h, item|
  h[item.slice(:type, :name)]  = item[:count]
  h
}.map { |k, v|
  {**k, count: v}
}
 

Комментарии:

1. Была бы менее «забавная» версия eatables.each_with_object(Hash.new(0)) { |h, memo| h[item.slice(:type, :name)] = item[:count] }.map {|k,v| k.merge(count: v) } . each_with_object это менее неудобно, когда вы изменяете хэш на каждой итерации.

2. @макс, я думаю, ты имел в виду eatables.each_with_object(Hash.new(0)) { |h, memo| memo[h.slice(:type, :name)] = h[:count] }.map... .

3. @CarySwoveland ой, да, это выглядит правильно.

Ответ №3:

Этот тип проблемы может быть решен с помощью сокращения

 output = eatables.reduce({}) do |hsh, current|
             if hsh.has_key?(current[:type] current[:name])
                 hsh[current[:type] current[:name]][:count]  = current[:count]
             else 
                hsh[current[:type] current[:name]] = current
             end
             hsh
         end.values
 

Комментарии:

1. Привет, спасибо за ответ, но вы не проверили :имя ключа

2. @alavnishubham Я также обновил код, чтобы проверить :name его.