[ruby-core:119822] [Ruby master Bug#20880] Hash allows array-type key duplicates

Issue #20880 has been reported by alexfrstnberg (Yana Prystopchuk). ---------------------------------------- Bug #20880: Hash allows array-type key duplicates https://bugs.ruby-lang.org/issues/20880 * Author: alexfrstnberg (Yana Prystopchuk) * Status: Open * ruby -v: 3.3.5 * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- I was solving small tasks on Leetcode and encountered an issue with Hash which looked strange to me: There's an array saved into the variable and a hash with a previously created array as a key ``` ruby arr = [1,2,3] hsh = {arr => 1} ``` ``` shell => {[1, 2, 3]=>1} ``` Modified the array. Added the same array to the same hash. ``` ruby arr << 4 hsh[arr] = 2 ``` ``` shell => {[1, 2, 3, 4]=>1, [1, 2, 3, 4]=>2} ``` Added another duplicate ``` ruby arr << 5 hsh[arr] = 3 ``` ``` shell => {[1, 2, 3, 4, 5]=>1, [1, 2, 3, 4, 5]=>2, [1, 2, 3, 4, 5]=>3} ``` ### First issue: As a user, I'd expect to have the already existing key reassigned with the new value. Since the key is duplicated, now it's not obvious which value *1*, *2*, or *3* should be returned for the key (*[1, 2, 3, 4, 5]* or *arr*). ### Second issue: When trying to actually retrieve a value, different methods behave differently: ``` ruby hsh[[1,2,3,4,5]] ``` ``` shell => 3 ``` ``` ruby hsh[arr] ``` ``` shell => 3 ``` **But** ``` ruby hsh.assoc(arr) ``` ``` shell => 1 ``` ### Third issue: Another example is created: ``` ruby arr = [1] hsh = {arr => 1} ``` And modified with the same logic using a loop: ``` ruby incr = 1 10.times do arr << (incr += 1) hsh[arr] = incr end ``` The received hsh: ``` shell => {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>9, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>2, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>5, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>6, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>7, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>8, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>11} ``` As you can see, the first key eventually got reassigned (there's no value 1 anymore, it was replaced by 9) I tried to add each next key manually and got the same result: 1 is replaced by 9. -- https://bugs.ruby-lang.org/

Issue #20880 has been updated by jeremyevans0 (Jeremy Evans). Status changed from Open to Rejected This is not a bug, it is expected. It's best not to mutate objects used as hash keys, but Ruby doesn't stop you from doing it. If you do mutate an object used as a hash key, you need to call rehash on the hash to update it (https://docs.ruby-lang.org/en/master/Hash.html#method-i-rehash): ```ruby arr = [1,2,3] hsh = {arr => 1} arr << 4 hsh.rehash hsh[arr] = 2 hsh # => {[1, 2, 3, 4]=>2} ``` ---------------------------------------- Bug #20880: Hash allows array-type key duplicates https://bugs.ruby-lang.org/issues/20880#change-110511 * Author: alexfrstnberg (Yana Prystopchuk) * Status: Rejected * ruby -v: ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin23] * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- I was solving small tasks on Leetcode and encountered an issue with Hash which looked strange to me: There's an array saved into the variable and a hash with a previously created array as a key ``` ruby arr = [1,2,3] hsh = {arr => 1} ``` ``` shell => {[1, 2, 3]=>1} ``` Modified the array. Added the same array to the same hash. ``` ruby arr << 4 hsh[arr] = 2 ``` ``` shell => {[1, 2, 3, 4]=>1, [1, 2, 3, 4]=>2} ``` Added another duplicate ``` ruby arr << 5 hsh[arr] = 3 ``` ``` shell => {[1, 2, 3, 4, 5]=>1, [1, 2, 3, 4, 5]=>2, [1, 2, 3, 4, 5]=>3} ``` ### First issue: As a user, I'd expect to have the already existing key reassigned with the new value. Since the key is duplicated, now it's not obvious which value *1*, *2*, or *3* should be returned for the key (*[1, 2, 3, 4, 5]* or *arr*). ### Second issue: When trying to actually retrieve a value, different methods behave differently: ``` ruby hsh[[1,2,3,4,5]] ``` ``` shell => 3 ``` ``` ruby hsh[arr] ``` ``` shell => 3 ``` **But** ``` ruby hsh.assoc(arr) ``` ``` shell => 1 ``` ### Third issue: Another example is created: ``` ruby arr = [1] hsh = {arr => 1} ``` And modified with the same logic using a loop: ``` ruby incr = 1 10.times do arr << (incr += 1) hsh[arr] = incr end ``` The received hsh: ``` shell => {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>9, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>2, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>3, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>5, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>6, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>7, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>8, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]=>11} ``` As you can see, the first key eventually got reassigned (there's no value 1 anymore, it was replaced by 9) I tried to add each next key manually and got the same result: 1 is replaced by 9. -- https://bugs.ruby-lang.org/
participants (2)
-
alexfrstnberg (Yana Prystopchuk)
-
jeremyevans0 (Jeremy Evans)