2013-10-03 5 views
2

У меня есть ассоциативный массив в рубине, который я хочу преобразовать в хэш. Этот хэш будет представлять первые значения в качестве ключа и суммы их вторых значений в качестве значения.Расчет ассоциативного массива Ruby

x = [[1,2],[1,3],[0,1],[0,2],[0,3],[1,5],[0,4],[1,6],[0,9],[1,9]] 

Как я могу получить хэш, как из этого ассоциативного массива?

{ 
    :0 => <sum_of_second_values_with_0_as_first_values>, 
    :1 => <sum_of_second_values_with_1_as_first_values> 
} 

ответ

3

Это не очень красивый, но он работает.

x = [[1,2],[1,3],[0,1],[0,2],[0,3],[1,5],[0,4],[1,6],[0,9],[1,9]] 

p Hash[ 
    x.group_by(&:first) 
    .map do |key, val| 
    [key,val.map(&:last).inject(:+)] 
    end 
] # => {1=>25, 0=>19} 

На второй мысли, это проще:

result = Hash.new(0) 
x.each{|item| result[item.first] += item.last} 
p result # => {1=>25, 0=>19} 
+0

Спасибо за ваш ответ! Я переписал это в более рубино-изящном виде, x.inject (Hash.new (0)) {| h, e | h [e [0]] + = e [1]; h} – Atul

1
x = [[1,2],[1,3],[0,1],[0,2],[0,3],[1,5],[0,4],[1,6],[0,9],[1,9]] 
arr_0,arr_1 = x.partition{|a,b| a==0 } 
Hash[0,arr_0.map(&:last).inject(:+),1,arr_1.map(&:last).inject(:+)] 
# => {0=>19, 1=>25} 

или

x = [[1,2],[1,3],[0,1],[0,2],[0,3],[1,5],[0,4],[1,6],[0,9],[1,9]] 
hsh = x.group_by{|a| a.first}.each_with_object(Hash.new(0)) do |(k,v),h| 
    h[k]=v.map(&:last).inject(:+) 
end 
hsh 
# => {1=>25, 0=>19} 
+0

Если у него 100 ключей, ему нужно 100 строк. Не очень общий ответ. – hirolau

+0

@hirolau Hummm, поэтому я добавил новый тоже .. :) –

2

Простое решение с помощью уменьшения. Он начинается с пустого хэша и итерации по всем элементам x. Для каждой пары он добавляет свое значение к элементу хэша в key (если этот индекс не был установлен раньше, по умолчанию 0). В последней строке задается переменная памяти hash для следующей итерации.

x.reduce(Hash.new(0)) { |hash, pair| 
    key, value = pair 
    hash[key] += value 
    hash 
} 

EDIT: набор хэш по умолчанию при инициализации

1

each_with_object также работает

[[1,2],[1,3],[0,1],[0,2],[0,3],[1,5],[0,4],[1,6],[0,9],[1,9]]. 
each_with_object(Hash.new(0)) {|(first,last), h| h[first] += last } 
# => {1=>25, 0=>19} 
Смежные вопросы