Search code examples
arraysrubystore

Ruby .store function changes hash values from array to single value


I am trying to create a hash where keys are number, and values is array [0,0] of counts from two arrays. what i am confused is why my_hash2.store(x,my_hash2[x][1]+1) don't update my counts.

my_hash2 = Hash.new{|h,k| h[k] = [0,0]}
[12,12,13,14,15,16].each do |x|
    my_hash2[x][0] += 1
end
puts my_hash2 # => {12=>[2, 0], 13=>[1, 0], 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]}
[12,12,13].each do |x|
    my_hash2.store(x,my_hash2[x][1]+1)
end
puts my_hash2 # => {12=>1, 13=>1, 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]}
puts my_hash2[12][0] #=> 1
puts my_hash2[12][1] #=> 0

Solution

  • .store associates the value given by value with the key given by key. (as per docs https://apidock.com/ruby/Hash/store)

    So this means that any value stored by your key is replaced by the new value.

    my_hash2 = Hash.new{|h,k| h[k] = [0,0]}
    [12,12,13,14,15,16].each do |x|
        my_hash2[x][0] += 1
    end
    puts my_hash2 # => {12=>[2, 0], 13=>[1, 0], 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]}
    [12,12,13].each do |x|
        # in the first run in case of 12 this replaces your [2, 0] with 1 because current value of my_hash2[12][1] is 0 and 0 + 1 is 1
        # in the second run we also get 12 but my_hash2[12] is 1 now. and 1[1] equals 0. You are here essentially doing my_hash[12] = 1[1] + 1 = 0 + 1 and it correctly gives you 1
        # in the third run it operates on my_hash2[13][1] but same rules apply
        my_hash2.store(x,my_hash2[x][1]+1)
    end
    puts my_hash2 # => {12=>1, 13=>1, 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]}
    puts my_hash2[12] #=> 1
    puts my_hash2[12][0] #=> 1
    puts my_hash2[12][1] #=> 0
    

    so you need to either not use .store or change this line:

    my_hash2.store(x,my_hash2[x][1]+1)
    

    to:

    new_val = [my_hash[x][0], my_hash[x][1]+1]
    my_hash2.store(x, new_val)
    

    the curious thing is why doing something like 1[0] will give you 1 but 1[1] will give you 0 (and not raise any errors)

    and the answer is again in the docs :)

    https://ruby-doc.org/core-2.5.0/Integer.html#method-i-5B-5D

    int[n] → 0, 1

    Bit Reference—Returns the nth bit in the binary representation of int, where int[0] is the least significant bit.

    this means that if we turn 1 into bit representation we then proceed to get the nth bit from that representation. And 1 has the bit on the 0 position and all other positions (so 1,2,3,4...) are all 0. That's why 1[0] gives you 1 but 1[1] or 1[3] will get you 0.