# 8/8 - Help confirming I understand a few things

#1

Looking for some help checking my understanding of the items below. Especially #3 which has me a confused. Much thanks in advance!!

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

The above code iterates over the words array, word is placed in the frequencies hash with a value of 1 initially, if the key already exists the value is incremented, if not a new key-value pair is created.

1. `frequencies = frequencies.sort_by{|word,count| count}`

The above code uses the sort_by method over the frequencies hash. As frequencies is a hash, we need two variables to iterate over, the count following |word, count| tells sort_by what weâ€™re â€¦ sorting by, and then stores the information in frequencies which is no longer a hash but an array of arrays.

`frequencies.each do |word,count| count = count.to_s puts "#{word} #{count}" end`

The above is where I get a bit confused. I thought frequencies was now an array of arrays, so I was thinking Iâ€™d have to use the method covered in an earlier lesson (an iterator within an iterator).

Sort_by changes frequencies to a 2D array so how does a hash each syntax |key,value| work later?
#2
1. Yes, that is correct.
2. No, it is still a hash, just sorted by `count`.
3. Because `frequencies` is still a hash, you can do it this way.

#3

Sorry, Iâ€™m also confused here. To make sure the value of the â€śfrequenciesâ€ť variable changes the type to array instead of hash Iâ€™ve put the â€śfrequencies.classâ€ť before calling â€ś.sort_byâ€ť and after.
And itâ€™s HASH before and ARRAY after!)
If thatâ€™s an array, how could we get the key and value to variables |word,count| instead of just getting the first â€śsub_arrayâ€ť to the word variable and nil to other (as I would have expected with 2D array)?

#4

When using the sort_by method on the hash object, what you get in return is a 2D array.

If you use the .inspect function on the frequencies variable before and after, you can get a more detailed look of the values.

Using an example string â€śTesting of multiples of arraysâ€ť

Executing frequencies.inspect before the sort will return
{â€śTestingâ€ť=>1, â€śofâ€ť=>2, â€śmultiplesâ€ť=>1, â€śarraysâ€ť=>1}

But if you do the same inspect afterwards, youâ€™ll see itâ€™s now an array instead
[[â€śTestingâ€ť, 1], [â€śarraysâ€ť, 1], [â€śmultiplesâ€ť, 1], [â€śofâ€ť, 2]]

When then executing the .each block on the 2D array with two parameters, it seems that Ruby knows to assign the first variable to the first value of the array, the second variable to the second value and so forth.

Iâ€™m afraid I donâ€™t know the precise logic as to how Ruby does it though, but it does seem to be a bit related how blocks in Ruby doesnâ€™t require precise number of arguments.

Iâ€™ve pasted an example below that I tried out, and it might demonstrate a bit on it works.
The comments below each statement is what the output was.

``````my_array = [[1,"Hello", false],[2,"Hey there", true],[3, "Howdy"]]

#I'm using 'p' instead of puts, since it's the same as running .inspect on the variable sent

p my_array
#[[1, "Hello", false], [2, "Hey there", true], [3, "Howdy"]]
#Here's the entire 2D array as it's been made above

my_array.each {|x| p x}
#[1, "Hello", false]
#[2, "Hey there", true]
#[3, "Howdy"]
#Here the .each will pass along each individual sub-array to the block, and print those out

my_array.each {|x,y,z| p "#{y}, #{x} - #{z}"}
#"Hello, 1 - false"
#"Hey there, 2 - true"
#"Howdy, 3 - "
#Here each element of the sub-array is passed to x, y and z. As you might notice in the last example, nothing is printed after the '-', since the original array only has two values in the third sub-array.``````

#5

Thank you very much for the detailed explanation, distrattos! Donâ€™t know why I was so sure that array behaves in a different way than hash with â€ś.eachâ€ť method)

Regarding the question 3) the confusing thing is that in â€śIterating Over Multidimensional Arraysâ€ť weâ€™ve actually iterated over each sub-array:

s = [[â€śhamâ€ť, â€śswissâ€ť], [â€śturkeyâ€ť, â€ścheddarâ€ť], [â€śroast beefâ€ť, â€śgruyereâ€ť]]
s.each do |sub_array|
sub_array.each do |x|
puts â€ś#{x}â€ť
end
end

However, knowing that each sub_array has 2 elements, we could just:

s = [[â€śhamâ€ť, â€śswissâ€ť], [â€śturkeyâ€ť, â€ścheddarâ€ť], [â€śroast beefâ€ť, â€śgruyereâ€ť]]
s.each do |x ,y|
puts x
puts y
end

So, looks like both variants are OK. But it is more flexible to iterate over each sub_array as we may not know the exact number of elements in each sub_array. For instance, if we get the input from the user.