0

I wrote a function which makes words of the same characters (but not the same sequence) into a hash[key], the key is a character-sorted string of these words for example, hash_list["arst"] => ["rats""tars""star"].

However, line 8 in my code perhaps does something wrong and when I puts word_list, I get a {}.

The ".txt" file consists of many lines of words like:

alean
allow
away
be
behavior
...
...

My code:

01 def findAnagrams()
02   word_list = Hash.new([]) # I set the default value here
03   # word_list.default = Array.new
04   File.open("/home/luchen/class/words.txt").each_line do |line|
05     word = line.chomp.strip.downcase
06     word_sort = word.chars.sort.join
07     # puts word+"------"+word_sort
08     word_list[word_sort].push(word)
09     # puts word_list[word_sort]
10   end 
11   puts word_list.to_s
12 end
13 
14 findAnagrams()
Mischa
  • 42,876
  • 8
  • 99
  • 111
lizlalala
  • 311
  • 4
  • 15

2 Answers2

3

Using Hash#new with an object as argument will return that same object as default value to any key that doesn't exist and will not add its value to the hash:

with_obj = Hash.new([])
with_obj[:test]
# => [] 
with_obj[:test] << 1
# => [1]
with_obj
# => {} # The :test key was not setted
with_obj[:test2]
# => [1] # The array object was changed when we did with_obj[:test] << 1

But you can initialize a hash using a block, and set the new key with the value you want. Using a block this way will initialize a new array every call:

with_block = Hash.new { |hash, key| hash[key] = [] }
with_block[:test]
# => [] 
with_block[:test] << 1
# => [1] 
with_block
# => {:test=>[1]} # This time the key is setted
with_block[:test2]
# => [] # And any new key will use a new instance of array
with_block
# => {:test=>[1], :test2=>[]} 
Doguita
  • 15,403
  • 3
  • 27
  • 36
1

You need to modify line 8 to something like:

word_list[word_sort] ||= []
word_list.push(word)

By just read-accessing the not-yet-existing hash element it is not created.

You have to write to it, i.e. you need to call []= on it, not just [].

undur_gongor
  • 15,657
  • 5
  • 63
  • 75
  • i initialize the value in Hash.new([]) and i thought in ruby it will automatically allocate space when hashing a new element just like C++ did...btw,i can't understand the ||=[] – lizlalala Oct 06 '15 at 15:16
  • That default value is returned if you look-up an unknown key. The key is not automatically added to the hash. For the methods, see the Ruby documentation: http://ruby-doc.org/core-2.2.3/Hash.html#method-i-5B-5D – undur_gongor Oct 06 '15 at 15:19
  • 1
    @lizlalala You can achieve this using a block instead like `Hash.new {|h, k| h[k] = []}`. – Doguita Oct 06 '15 at 15:20
  • @Doguita: True. I think you should post this as an answer. – undur_gongor Oct 06 '15 at 15:22
  • i set the default value in line 2...is there any difference?@Doguita – lizlalala Oct 06 '15 at 15:33