hash of arrays

D

David Sprague

I'm wrote this code to bin a list of words by word-length:

dict = Hash.new([])

dict_file.each do |line|
line.chomp!()
dict[line.length] << line
end

expecting that I could avoid testing each time whether this was a new
entry in the hash or not by just appending to the default, an empty
array,
if it is new.

What happens is that the *same* array is assigned as the default value
to all new entries so that all the hash entries finish with the same
array of values.

is there away to void having to write something like:

if dict.key?(line.length)
dict[line.length] << line
else
dict[line.length] = line
end

or the ternary equivalent in the inner loop?

thanks,

Dave
 
R

Roger Braun

Hi David

2011/4/13 David Sprague said:
I'm wrote this code to bin a list of words by word-length:

dict =3D Hash.new([])

dict_file.each do |line|
=C2=A0line.chomp!()
=C2=A0dict[line.length] << line
end

expecting that I could avoid testing each time whether this was a new
entry in the hash or not by just appending to the default, an empty
array,
if it is new.

See http://ruby-doc.org/core/classes/Hash.html#M000718.
What happens is that the *same* array is assigned as the default value
to all new entries so that all the hash entries finish with the same
array of values.

is there away to void having to write something like:

if dict.key?(line.length)
=C2=A0dict[line.length] << line
else
=C2=A0dict[line.length] =3D line
end

dict =3D Hash.new{Array.new} should work.

--=20
Roger Braun
rbraun.net | humoralpathologie.de
 
T

Tom Reilly

Define hash of hashes this way

#Using a default hash.

foo = Hash.new { |hash, key| hash[key] = Hash.new }

foo["a"][1] = "one"
foo["a"][2] = "a two"
foo["b"][3] = "b three"
foo["a"][4] = "b four"

p foo["a"][1]
p foo["a"][4]
p foo["a"].size
foo["a"].each {|x,y| p "#{x} #{y}"}
 
R

Roger Braun

is there away to void having to write something like:

if dict.key?(line.length)
=C2=A0dict[line.length] << line
else
=C2=A0dict[line.length] =3D line
end

dict =3D Hash.new{Array.new} should work.

Sorry, I meant Hash.new{|hash,key| hash[key] =3D []}

--=20
Roger Braun
rbraun.net | humoralpathologie.de
 
J

jake kaiden

David Sprague wrote in post #992397:
I'm wrote this code to bin a list of words by word-length:

hi david,
if you're just trying to group words by their length, i'm not sure why
you need a hash of arrays, a simple hash would do...

list = %W[a cd def ghi jklm]
hash = {}
list.collect{|entry| hash[entry.length] = entry}
p hash

=> {1=>"a", 2=>"cd", 3=>"ghi", 4=>"jklm"}

the problem here is that any words of the same length would result in
only one key (the last one) having the value of the word. you could
just switch, and use the word as the key, and the length as the value...

list.collect{|entry| hash[entry] = entry.length}

=> {"cd"=>2, "a"=>1, "jklm"=>4, "def"=>3, "ghi"=>3}

but of course if you repeat words, you'll have the same problem. the
quickest (and probably dumbest) solution i can think of is adding some
kind of "unique id" to each key, so that they don't get lost -

list = %W[a cd def ghi jklm]
hash = {}
uniqueID = 0
x = 0
while x < list.length
hash ["#{list[x].length}.#{uniqueID}"] = list[x]
x += 1
uniqueID += 1
end
hash.sort.each{|k, v| p "#{k}, #{v}"}

=>"1.0, a"
"2.1, cd"
"3.2, def"
"3.3, ghi"
"4.4, jklm"

you could then call a String#split (or something better and easier,
i'm winging it here,) on the keys, to get all the words that are 3
letters long, etc...

hashes of arrays certainly are cool though, and it might be fun to
play with them...

foo = Hash.new{|key, value| key[value] = []}

foo ["rays"] = %W[alpha beta gamma]
foo ["planets"] = %W[mercury venus earth mars]
foo ["colors"] = %W[red orange yellow green blue indigo violet]

p foo
p foo.length
p foo ["rays"][1]
p foo ["planets"][-1]
p foo ["colors"].length

-j
 
B

botp

dict =3D Hash.new([])

dict_file.each do |line|
=A0line.chomp!()
=A0dict[line.length] << line
end

there are many ways.
one way eg,

dict=3D{}
dict_file.each do |line|
line.chomp!
(dict[line.length] ||=3D []) << line
end

best regards -botp
 
W

WJ

David said:
I'm wrote this code to bin a list of words by word-length:

dict = Hash.new([])

dict_file.each do |line|
line.chomp!()
dict[line.length] << line
end

words = IO.read( "data2" ).strip.split( /\s+/ )
dict = words.group_by{|w| w.size}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,059
Latest member
cryptoseoagencies

Latest Threads

Top