Вы можете использовать три Enumerable методы: group_by
, map
и reduce
(ака inject
):
arr.group_by(&:first).map { |k,v| [k, v.map(&:last).reduce(:+)] }
#=> [["BEER", 313],["FOOD", 167]]
стадии:
h = arr.group_by(&:first)
# => {"BEER"=>[["BEER", 37], ["BEER", 95], ["BEER", 85], ["BEER", 60],
# ["BEER", 36]],
# "FOOD"=>[["FOOD", 31], ["FOOD", 86], ["FOOD", 50], ["FOOD", 0]]}
map
присвоит блочные переменные первого элемент (значение ключа pa л) из h
:
k = "BEER"
v = [["BEER", 37], ["BEER", 95], ["BEER", 85], ["BEER", 60], ["BEER", 36]]
затем выполняет вычисление блока:
[k, v.map(&:last).reduce(:+)]
#=> ["BEER", [37, 95, 85, 60, 36].reduce(:+)]
# ["BEER", 313]
Второй элемент h
передается к блоку:
k = "FOOD"
v = [["FOOD", 31], ["FOOD", 86], ["FOOD", 50], ["FOOD", 0]]
[k, v.map(&:last).reduce(:+)]
#=> ["FOOD", [31, 86, 50, 0].reduce(:+)]
# ["FOOD", 167]
Если пары arr
известны которые должны быть сгруппированы первым элементом пары, как они приведены в примере, мы могли бы использовать Enumerable#chunk:
arr.chunk(&:first).map { |k,v| [k, v.map(&:last).reduce(:+)] }
1 Поскольку ключи хеширования Ruby v1.9 заказываются по их порядку размещения. Поэтому каждый может ссылаться на n-й элемент (пару-ключ-значение) хэша. До v1.9 не было понято, какие ключи хеша заказываются. Для этих версий приведенный выше код работает нормально, но мы не знаем, какой порядок пар ключ-значение передается map
его блоку.
Rails! = Ruby. Ваша проблема в Ruby, а не в Rails. –
@SimoneCarletti Мне нужно это внутри моего приложения rails :) – xxx
@xxx Это не имеет значения, это проблема Ruby. В этом случае факт, что ваш код находится в действии Rails или действии Sinatra, не имеет никакого значения. Вы управляете «массивом» с помощью Ruby, а не с Rails. –