RailsNewbie
RailsNewbie

Reputation: 155

Iterating "For" loop with 2 brackets

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

Answers (4)

Jason Adrian Bargas
Jason Adrian Bargas

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

RailsNewbie
RailsNewbie

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

pangpang
pangpang

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

Mureinik
Mureinik

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

Related Questions