Reputation: 193
I'm for some reason hitting a wall here. I need help figuring this out please. I have the following type of 2D array:
[["Bob", "Car", 25000],
["Bob", "TV", 5000],
["Bob", "dog", 1000],
["Sue", "Cat", 1000],
["Sue", "Car", 10000],
["Bob", "shoes", 100],
["Carol", "car", 20000]]
And I need to generate an array that is the sum of each of these people's total from the third element of each sub array. ie:
[["Bob", 31100],
["Sue", 11000],
["Carol", 20000]]
Right now I have a complicated and contrived solution using two loops that iterate through the entire array for each of its own elements. Is there an easier more streamlined way to do this? Especially since my data sets will be quite large. I know ruby has a bunch of awesome enumerables that seem like would fit here, but I can't quite think of how to fit them in.
Upvotes: 2
Views: 53
Reputation: 35064
.group_by(&:first).map do |who, group|
[who, group.map(&:last).inject(:+)]
end
Upvotes: 1
Reputation: 110675
You can use a counting hash:
arr = [["Bob", "Car", 25000],
["Bob", "TV", 5000],
["Bob", "dog", 1000],
["Sue", "Cat", 1000],
["Sue", "Car", 10000],
["Bob", "shoes", 100],
["Carol", "car", 20000]]
arr.each_with_object(Hash.new(0)) { |(name,_,total),h| h[name] += total }
#=> {"Bob"=>31100, "Sue"=>11000, "Carol"=>20000}
Hash::new is used to create a hash with a default value of zero. That means that if the hash h
does not have a key name
, h[name]
returns zero. Since:
h[name] += total
expands to:
h[name] = h[name] + total
h[name]
on the right side of the equality returns zero when h
does not have a key name
.
Upvotes: 4
Reputation: 127
arr = [["Bob", "Car", 25000],
["Bob", "TV", 5000],
["Bob", "dog", 1000],
["Sue", "Cat", 1000],
["Sue", "Car", 10000],
["Bob", "shoes", 100],
["Carol", "car", 20000]]
hash_result = Hash.new(0)
arr.each do |record|
hash_result[record[0]] += record[2]
end
This will give you a hash result. If you want an array, just call to_a
on hash_result
.
Upvotes: 1
Reputation: 164679
You can iterate through the array of purchases and store the totals in a hash.
purchases = [
["Bob", "Car", 25000],
["Bob", "TV", 5000],
["Bob", "dog", 1000],
["Sue", "Cat", 1000],
["Sue", "Car", 10000],
["Bob", "shoes", 100],
["Carol", "car", 20000]
]
totals = Hash.new(0) # initialize the values to 0
purchases.each { |purchase|
totals[purchase[0]] += purchase[2]
}
Upvotes: 1