If I call the function anagrams
below in irb, I get a non-empty hash container as expected. But if you comment out the print "No Key\n"
line, the returned hash container is now empty. In fact for all elements in list the code in the elsif
branch seems to execute. Either I'm going nuts or there is a nasty bug here:
def anagrams(list = ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams', 'scream'])
aHash = Hash.new()
list.each { |el|
aKey = el.downcase.chars.sort.to_a.hash
if aHash.key?(aKey)
# print "Has Key\n"
aHash[aKey] << el
elsif
# print "No Key\n"
aHash[aKey] = [el]
end
}
return aHash
end
I have the following versions of ruby and irb installed:
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]
irb 0.9.6(09/06/30)
Your problem is that you're using an
elsif
where you meanelse
. This:is misleading formatting, it is actually interpreted more like this:
but
print
returnsnil
so the logic is like this:and
nil
is false in a boolean context soaHash[aKey] = [el]
never occurs. If you remove theprint
then you end up with this:and the assignment occurs; the assignment is also true in a boolean context (because an Array is) but the truthiness is irrelevant in this case.
You want to use
else
here:Even better would be to use a Hash with an Array (via a block) as its default value:
and then you don't need the
if
at all, you can just do this:And you can use anything as a key in a Ruby Hash so you don't even need to
.to_a.hash
, you can simply use the Array itself as the key; furthermore,sort
will give you an array so you don't even need theto_a
:Someone will probably complain about the
return
at the end of your method so I'll do it: you don't need thereturn
at the end of your method, just sayaHash
and it will be the method's return value:You could also use
each_with_object
to compress it even more:but I'd probably do it like this to cut down on the noise: