Reputation: 155
I am reading Programming Ruby (4th Edition) and I don't quite understand how we can iterate a for
loop with 2 brackets.
require_relative "words_from_string.rb"
require_relative "count_frequency.rb"
raw_text = %{hey hey hey man man bro}
word_list = words_from_string(raw_text)
counts = count_frequency(word_list)
sorted = counts.sort_by {|word, count| count }
top_five = sorted.last(5)
for i in 0...5
word = top_five[i][0] #don't understand why there are 2 brackets.
count = top_five[i][1] #how does the iterator work with 2 brackets.
puts "#{word}: #{count}"
end
words_from_string.rb
def words_from_string(string)
string.downcase.scan(/[\w']+/)
end
count_frequency.rb
def count_frequency(word_list)
counts = Hash.new(0)
for word in word_list
counts[word] += 1
end
counts
end
Upvotes: 2
Views: 74
Reputation: 254
It's because 'topfive' is a multi-dimensional array (a two-dimension in your case), meaning, it is an array, containing an array.
If you're going to play around with it: If you puts topfive[n], it will give you an array that has a structure of [string, int], which is the [word,count] in your example.
The code uses two brackets in order for you to access the elements inside the array. In the example, topfive[i][0] will get the word, and topfive[i][1] will get the count or the number of words
Upvotes: 2
Reputation: 155
I played around with my console and based on your answers, i finally got it!
So essentially, first [ ] is the index of the main array and the second [ ] is the index for the nested array. Now i get it! Brilliant! Thanks guys!
def words_from_string(string)
string.downcase.scan(/[\w']+/)
end
def count_frequency(word_list)
counts = Hash.new(0)
for word in word_list
counts[word] += 1
end
counts
end
raw_text = %{hey hey hey man man bro yo yo yo yo yo ye ye ya oi ui}
word_list = words_from_string(raw_text)
counts = count_frequency(word_list)
sorted = counts.sort_by {|word, count| count}
top_five = sorted.last(5)
print word_list
#produces
["hey", "hey", "hey", "man", "man", "bro", "yo", "yo", "yo", "yo", "yo", "ye", "ye", "ya", "oi", "ui"]
print counts
#produces
{"hey"=>3, "man"=>2, "bro"=>1, "yo"=>5, "ye"=>2, "ya"=>1, "oi"=>1, "ui"=>1}
print sorted
#produces
[["ui", 1], ["ya", 1], ["oi", 1], ["bro", 1], ["man", 2], ["ye", 2], ["hey", 3], ["yo", 5]]
print top_five
#produces
[["bro", 1], ["man", 2], ["ye", 2], ["hey", 3], ["yo", 5]]
for i in 0...5
word = top_five[i][0]
count = top_five[i][1]
puts "#{word}: #{count}"
end
#produces
bro: 1
man: 2
ye: 2
hey: 3
yo: 5
puts top_five[4][1]
#produces
"5"
puts top_five[4][0]
#produces
"yo"
Upvotes: 1
Reputation: 8821
If you use sort_by
for hash, it convert hash to two-dimensional array.
counts = Hash.new(0)
=> {}
counts[1] = 2
=> 2
counts[2] = 1
=> 1
counts
=> {1=>2, 2=>1}
sorted = counts.sort_by{ |k, v| v }
=> [[2, 1], [1, 2]]
sorted[0][1]
=> 1
Upvotes: 2
Reputation: 311393
The top_five
array is made up of elements which are themselves arrays with two elements - the first is the word and the second is the number of times it appeared in raw_text
.
The loop iterates over these pairs and extracts the word (the first element of each array, index 0) to word
and the count (the second element in each array, index 1) to count
.
Upvotes: 2