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
elsifwhere you meanelse. This:is misleading formatting, it is actually interpreted more like this:
but
printreturnsnilso the logic is like this:and
nilis false in a boolean context soaHash[aKey] = [el]never occurs. If you remove theprintthen 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
elsehere: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
ifat 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,sortwill give you an array so you don’t even need theto_a:Someone will probably complain about the
returnat the end of your method so I’ll do it: you don’t need thereturnat the end of your method, just sayaHashand it will be the method’s return value:You could also use
each_with_objectto compress it even more:but I’d probably do it like this to cut down on the noise: