Barris
Barris

Reputation: 1019

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?

Upvotes: 3

Views: 1612

Answers (3)

John La Rooy
John La Rooy

Reputation: 304147

frequencies seems to be a poor choice of variable name from the description.

Any reason why you can't just

words = "foo bar baz"
=> "foo bar baz"
words.split.map.with_index.to_h
=> {"foo"=>0, "bar"=>1, "baz"=>2}

Upvotes: 0

Max
Max

Reputation: 22325

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

Upvotes: 1

Yu Hao
Yu Hao

Reputation: 122383

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

Upvotes: 2

Related Questions