Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating Hash value in Ruby

What i'd like to do is push a bunch of user inputted strings, separated by their spaces to Hash Keys and assign each of those Keys a numerical value from 0 upwards in their order of input. For example;

User input: "a s d f b"

Result:

a => 0
b => 1
c => 2
d => 3
f => 4
b => 5

But my code is only outputting 0 with no increment, please see my code below;

puts "Please enter data:"
text = gets.chomp
words = text.split(" ")
    frequencies = Hash.new(0)

words.each do |k|
    frequencies[k] += 1
end

frequencies.each do |x,y|
    puts x + " " + y.to_s
end

Can anyone see what's wrong with the code above?

like image 836
Barris Avatar asked Dec 05 '25 10:12

Barris


2 Answers

The default value of every key in this Hash is 0, so by

frequencies[k] += 1

You are incrementing every value (of non-existing key) from 0 to 1.

A simple fix is to use an external counter as the value:

counter = 0
words.each do |k|
    frequencies[k] = counter
    counter += 1
end
like image 175
Yu Hao Avatar answered Dec 07 '25 04:12

Yu Hao


Your code doesn't work because

frequencies[k] += 1

Is like

frequencies[k]    = frequencies[k] + 1
# ^ set new value   ^ get default value (i.e. 0)

The default value never changes, so every key gets the same default value of 0 and adds one to it.

You could explicitly increment the default value each time

words.each do |k|
  frequencies[k] = frequencies.default += 1
end

But I think the more Rubyish solution is to use the indices of the keys (since that's what the "numerical values" are). each_with_index gives you each key with it's corresponding index, and to_h turns these pairs into a Hash.

frequencies = text.split.each_with_index.to_h

egwspiti is correct that older versions of Ruby don't have Enumerable#to_h. In that case you can do

words.each_with_index do |k, i|
    frequencies[k] = i
end
like image 40
Max Avatar answered Dec 07 '25 04:12

Max