Iterate through hash issues

Hey all, my first post.

ruby 1.8.7 on RHEL 6.

Trying to build a hash, populate it, and then print it in a particular
order. The output is not what I’m looking for. Some hash keys look odd
and some puts statements fail. Since I’m new to Ruby my guess is
“operator error”. Would appreciate being pointed in the right
direction. Sample output is below the code.

#!/usr/bin/env ruby

def roll2
return 2 + rand(6) + rand(6)
end

def hexconvert(num)
if num > 9
makecap = true
end

num = num.to_s(16)

if makecap
num = num.capitalize
end

return num
end

def make_stat
roll = roll2
return hexconvert(roll)
end

stats = {
‘Str’ => nil,
‘Dex’ => nil,
‘End’ => nil,
‘Int’ => nil,
‘Edu’ => nil,
‘Soc’ => nil
}

stats.each do |stat|
stats[stat] = make_stat
puts “#{stat} is #{stats[stat]}.”
end

puts “.” * 10

stats_names = [‘Str’, ‘Dex’, ‘End’, ‘Int’, ‘Edu’, ‘Soc’]
stats_names.each { |stat| puts “#{stat} is #{stats[stat]}.”}

puts “.” * 10

Sample output

./exercises.rb
Soc is 3.
Int is 8.
End is A.
Dex is 3.
Dex3 is 4.
Str is 7.
Soc3 is 8.
Soc38 is 7.
Edu is 5.

Str is .
Dex is .
End is .
Int is .
Edu is .
Soc is .

Desired output

Str is 7
Dex is 3
End is A
Int is 8
Edu is 5
Soc is 7

stats.each should be replaced with stats.each_key.

On Fri, Oct 3, 2014 at 2:53 PM, John W Higgins [email protected]
wrote:

stats.each should be replaced with stats.each_key.

John, thanks! That did it.

On 14-10-03, 11:42, leam hall wrote:

Hey all, my first post.

ruby 1.8.7 on RHEL 6.

Trying to build a hash, populate it, and then print it in a particular
order. The output is not what I’m looking for. Some hash keys look odd
and some puts statements fail. Since I’m new to Ruby my guess is
“operator error”. Would appreciate being pointed in the right
direction. Sample output is below the code.

hash.each is actually “each_pair” so you get the keys and values. You
can do it this way:

 stats.each do |name, count|
   puts "#{name} is #{count}"
 end

If you don’t give a pair of arguments to the block like above, you will
get them as an array of [key, value].

Andrew V.

On 2014-Oct-3, at 14:42 , leam hall [email protected] wrote:

#!/usr/bin/env ruby

def roll2
return 2 + rand(6) + rand(6)
end

This could be:
def roll(spec)
number, sides = spec.split(‘d’,2).map {|n|n.to_i}
result = 0
number.times { result += 1 + rand(sides) }
result
end

Then you could do:

roll(‘2d6’)

irb1.8.7> Array.new(50) { roll(‘2d6’) }
#1.8.7 => [6, 4, 5, 3, 8, 8, 9, 5, 11, 3, 3, 8, 7, 4, 6, 7, 4, 8, 10,
10, 8, 5, 6, 10, 6, 4, 10, 9, 6, 9, 4, 7, 8, 4, 5, 8, 6, 9, 8, 7, 2, 5,
9, 6, 7, 7, 11, 8, 12, 6]

return num
end

Try this, it’s much simpler.
def hexconvert(num)
num.to_s(16).upcase
end

def make_stat
roll = roll2
return hexconvert(roll)
end

Converting make_stat I’ll leave as an exercise for you :slight_smile:

stats = {
‘Str’ => nil,
‘Dex’ => nil,
‘End’ => nil,
‘Int’ => nil,
‘Edu’ => nil,
‘Soc’ => nil
}

stats.each do |stat|
This is your problem. Hash#each returns the key and the value. You’re
capturing something like [‘Soc’,nil] the first time through and then
assign stats[[‘Soc’,nil]]=3 but the output looks kinda OK because
[‘Soc’,nil].to_s is just “Soc”
Try using either:
stats.each do |stat,value|
or, probably better:
stats.keys.each do |stat|
as that also avoids changing the Hash while it is still being iterated.

stats[stat] = make_stat
puts “#{stat} is #{stats[stat]}.”
end

puts “.” * 10

stats_names = [‘Str’, ‘Dex’, ‘End’, ‘Int’, ‘Edu’, ‘Soc’]
If you initialized stats={} and then did stats_names.each do |stat|
above, you’d really avoid problems. If you want the output in a
particular order, you should do this anyway. (If you update your Ruby
version, 1.9+ Hash maintains insertion order even though a Hash is
inherently unordered.)
End is A.
Int is .
Dex is 3
End is A
Int is 8
Edu is 5
Soc is 7


Mind on a Mission

Try that and you should also get familiar with irb (or, later, one of
it’s cousins like ‘pry’ available as a gem) to run code interactively.

-Rob