user2259723
user2259723

Reputation: 13

How do I add an object to an array, where the array is a value to a key in a hash?

So basically my code is as follows

anagrams = Hash.new([])
self.downcase.scan(/\b[a-z]+/i).each do |key|
  anagrams[key.downcase.chars.sort] = #push key into array
end

so basically the hash would look like this

anagrams = { "abcdef" => ["fdebca", "edfcba"], "jklm" => ["jkl"]}

Basically what I don't understand is how to push "key" (which is obviously a string) as the value to "eyk"

I've been searching for awhile including documentation and other stackflow questions and this was my best guess

anagrams[key.downcase.chars.sort].push(key)

Upvotes: 0

Views: 38

Answers (2)

mu is too short
mu is too short

Reputation: 434685

Your guess:

anagrams[key.downcase.chars.sort].push(key)

is right. The problem is your hash's default value:

anagrams = Hash.new([])

A default value doesn't automatically create an entry in the hash when you reference it, it just returns the value. That means that you can do this:

h = Hash.new([])
h[:k].push(6)

without changing h at all. The h[:k] gives you the default value ([]) but it doesn't add :k as a key. Also note that the same default value is used every time you try to access a key that isn't in the hash so this:

h = Hash.new([])
a = h[:k].push(6)
b = h[:x].push(11)

will leave you with [6,11] in both a and b but nothing in h.

If you want to automatically add defaults when you access them, you'll need to use a default_proc, not a simple default:

anagrams = Hash.new { |h, k] h[k] = [ ] }

That will create the entries when you access a non-existent key and give each one a different empty array.

Upvotes: 1

Jordan Running
Jordan Running

Reputation: 106037

It's not entirely clear what your method is supposed to do, but I think the problem is that you don't have an array to push a value onto.

In Ruby you can pass a block to Hash.new that tells it what to do when you try to access a key that doesn't exist. This is a handy way to automatically initialize values as empty arrays. For example:

hsh = Hash.new {|hsh, key| hsh[key] = [] }
hsh[:foo] << "bar"
p hsh # => { :foo => [ "bar" ] }

In your method (which I assume you're adding to the String class), you would use it like this:

class String
  def my_method
    anagrams = Hash.new {|hsh, key| hsh[key] = [] }

    downcase.scan(/\b[a-z]+/i).each_with_object(anagrams) do |key|
      anagrams[key.downcase.chars.sort.join] << key
    end
  end
end

Upvotes: 0

Related Questions