Reputation: 14498
I am iteratively assigning elements to a hash whose values are an array consisting of an integer and an array. A toy example of my current strategy is this (incrementing the first element of the array, and pushing a number to the second element of the array):
aHash = Hash.new([0, []])
[1,3,5,1,1].each do |x|
aHash[x] = [aHash[x][0] + 1, aHash[x][1] << x]
end
aHash # => {1=>[3, [1, 3, 5, 1, 1]], 3=>[1, [1, 3, 5, 1, 1]], 5=>[1, [1, 3, 5, 1, 1]]}
The incrementing portion of the loop appears to be working, however appending each array is not. The desired hash should look like this:
aHash # => {1=>[3, [1, 1, 1]], 3=>[1, [3]], 5=>[1, [5]]}
I have also tried:
[1,3,5,1,1].each do |x|
aHash[x] = [aHash.values_at(x)[0][0] + 1, aHash.values_at(x)[0][1] << x]
end
aHash # => {1=>[3, [1, 3, 5, 1, 1]], 3=>[1, [1, 3, 5, 1, 1]], 5=>[1, [1, 3, 5, 1, 1]]}
But am getting this same incorrect result.
That being said, my questions are:
Upvotes: 0
Views: 181
Reputation: 13901
If I was trying to get the result you are looking for I would use the group_by function.
a = [1,3,5,1,1]
p a.group_by{|x|x} #=> {5=>[5], 1=>[1, 1, 1], 3=>[3]}
And if you really want the format you asked for:
a = [1,3,5,1,1]
a_transformed = a.group_by{|x|x}.map{|x|[x.first,[x.last.size,x.last]]}
p Hash[a_transformed] #=> {1=>[3, [1, 1, 1]], 3=>[1, [3]], 5=>[1, [5]]}
Upvotes: 0
Reputation: 22325
aHash = Hash.new([0, []])
Objects are passed by reference in Ruby. You are creating one array for the default value ([0, []]
) and passing a reference to that same array every time you access a missing key.
The solution is to create your default array inside a block, so that it gets reevaluated with each missing key:
aHash = Hash.new { [0, []] }
Upvotes: 2