Ruby Hash with duplicate keys?

26,482

Solution 1

This would kinda defeat the purpose of a hash, wouldn't it?

If you want a key to point to multiple elements, make it point to an array:

h = Hash.new { |h,k| h[k] = [] }
h[:foo] << :bar
h #=> {:foo=>[:bar]}
h[:foo] << :baz
h #=> {:foo=>[:bar, :baz]}

Solution 2

Two ways of achieving duplicate keys in a hash:

h1 = {}
h1.compare_by_identity
h1["a"] = 1
h1["a"] = 2
p h1 # => {"a"=>1, "a"=>2}


h2 = {}
a1 = [1,2,3]
a2 = [1,2]
h2[a1] = 1
h2[a2] = 2
a2 << 3 
p h2 # => {[1, 2, 3]=>1, [1, 2, 3]=>2}
Share:
26,482

Related videos on Youtube

B Seven
Author by

B Seven

Status: Hood Rails on HTTP/2: Rails HTTP/2 Rack Gems: Rack Crud Rack Routing Capybara Jasmine

Updated on July 09, 2022

Comments

  • B Seven
    B Seven almost 2 years

    Is it possible to create a hash in Ruby that allows duplicate keys?

    I'm working in Ruby 1.9.2.

    • Thiago Jackiw
      Thiago Jackiw almost 13 years
      Short answer is no, hashes need to have unique keys. Why would you need to have a hash with duplicate keys?
    • Ray Toal
      Ray Toal almost 13 years
      Do you mean an instance of the class Hash that has two entries, each of which with the same exact key?
    • Admin
      Admin almost 13 years
      You don't want this, you'd need to ruin performance to allow this.
    • John La Rooy
      John La Rooy almost 13 years
      @Thiago, that's a sort of medium answer. The short answer is "No" :)
    • PJP
      PJP about 8 years
      Perhaps reading the documentation would help: "A Hash is a dictionary-like collection of unique keys and their values."
  • B Seven
    B Seven almost 11 years
    The first example is exactly what I was looking for. Awesome.
  • Buddy
    Buddy about 10 years
    Hello Steenslag, i used "compare_by_identity" for creating hash with duplicate keys. But it is not working. Will you please help me.
  • steenslag
    steenslag about 10 years
    @Buddy What are you using as keys? Integers and symbols can't work, there is only one 1 and one :a - duplicates are impoissible. compare_by_identity works by comparing object_id's, normal hashes compare by comparing the result of the eql? method.
  • Cyril Duchon-Doris
    Cyril Duchon-Doris over 9 years
    It actually depends on the context. For example, in LDAP systems, you can have multiple objectClass, and yes, you can define a hash like this one : attrs = { ..., displayName: user.short_name, objectClass: "organizationPerson", objectClass: "person", objectClass: "top", objectClass: "user", i }
  • Michael Kohl
    Michael Kohl over 9 years
    That may well be the case, but that doesn't turn it into an associative array (which is what Ruby hashes are). "In computer science, an associative array, map, symbol table, or dictionary is an abstract data type composed of a collection of (key, value) pairs, such that each possible key appears just once in the collection." Emphasis added.
  • Emile Vrijdags
    Emile Vrijdags almost 7 years
    C++ has multimaps and multisets that allow multiple keys with the same name. From that same wikipedia page on associative arrays: "A multimap generalizes an associative array by allowing multiple values to be associated with a single key." So I would not say it defeats the purpose.. but its just a different, and valid usecase.
  • Michael Kohl
    Michael Kohl almost 7 years
    Sure, but if you look at the C++ template for multimap you'll also see that it's a more complex data structure than a simple associative array which is what Ruby hashes are. There are multimap gems for Ruby, e.g. github.com/doxavore/multimap.
  • starfry
    starfry over 6 years
    You had me going there for a moment... the first example is what I needed right now. It works with Ruby 1.9.3 but not with Ruby 2.2.1 (just two versions selected for a quick test).
  • steenslag
    steenslag over 6 years
    Strange... it does not work on 2.3.3, but it does work on 2.4.2 ?!
  • ivanibash
    ivanibash about 6 years
    We had a similar problem at my company and my boss came up with a solution to make the first example work in all ruby versions. Basically in some rubies (latest?) it seems like when you write h1['a'] two times, a string object gets created with different ids. This is not the case in som other versions. In other versions when you write h1['a'] twice the id of that 'a' will be the same each time. A workaround is to do h1['a'.clone] to create a new string object.
  • code_aks
    code_aks about 5 years
    So, How can I get value of key from h1 hash ??
  • Karin
    Karin almost 2 years
    i tried this but somehow doesn't work, i used this instead and it works for me stackoverflow.com/a/36336793/11976278