2

I have an associative array in ruby which I want to convert into a hash. This hash will represent the first values as key and sum of their second values as its value.

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

How can I get a hash like the following from this associative array?

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

4 Answers 4

3

It is not very beautiful but it works.

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}

On second thought, this is simpler:

result = Hash.new(0)
x.each{|item| result[item.first] += item.last}
p result # => {1=>25, 0=>19}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your answer! I rewrote this in a more ruby-elegant way, x.inject( Hash.new(0)){ |h,e| h[e[0]] += e[1]; h }
2

An easy solution using reduce. It starts with an empty Hash and iterates over all elements of x. For each pair it adds its value to the hash element at key (if this index wasn't set before, default is 0). The last line sets the memory variable hash for the next iteration.

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

EDIT: set hash default at initialization

Comments

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}

or

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}

2 Comments

If he has 100 keys he need 100 lines. Not a very general answer.
@hirolau Hummm so I added a new one also.. :)
1

each_with_object also works

[[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}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.