Iterating Over Multidimensional Arrays


#1

I'm not stuck on this exercise, I just don't understand it. Where does sub_array come from? & Why are we using Y instead of x? I guess the syntax just doesn't make sense to me. Can someone please explain why it is the way it is?

s = [["ham", "swiss"], ["turkey", "cheddar"], ["roast beef", "gruyere"]]

s.each do | sub_array |
sub_array.each do | y |
puts y
end
end


#2

You're defining those variables in your loops, you can call them anything you like and should generally aim to choose names that match what the value represents


#3

Sorry I am still struggling with this concept so pardon my ignorance. Are you saying that when I use the "do" control I am in a sense defining a variable? As I thought we defined variables with "=". Where in that code is sub_array defined and what is it defined as?


#4

I suggest having a look at various tutorials' loop sections where you can pick and choose between different explanations of what's going on.

Explaining this involves procs blocks and methods, so I would have to explain those before I could even start. Better if you go read up on them where you can read as much or as little as you want, I can't guess what that would be (Your question is too unspecific/broad because of what information you're likely missing. You might not want a very long answer, but that's also covered by having a look at what various tutorials have to say on it, read as much or as little as you want)


#5

I'm replying with my understanding :smiley: though I am no pro (so experts feel free to correct)!

You're probably used to seeing something like:
s.each { |x| puts x}
and this basically is a shorter way of writing
s.each do |x| puts x end

In both of the above, you can think of x as being like a throw-away variable being used for the loop, and Ruby understands that it is a variable from the use of the vertical lines ||.
In the actual example, they are using 'y' and 'sub_array' as alternatives to 'x' for the parameters (variables) of the blocks (loops).


The thing I'm not sure about, is how this approach differs to...
s.each {|x| puts x}
as this seems to return the same result; each element of the array and sub-array.


#7

Ruby's 'puts' has some crazy behavior when dealing with arrays, but 'print' does not. I fiddled with it in 12/16 awhile and this is what I found:

s = [["ham", "swiss"], ["turkey", "cheddar"], ["roast beef", "gruyere"]]

# This breaks down sub-arrays and prints each element on its own line.
#   Not what was wanted, but it fools the evaluator.
s.each { |x| puts x }
puts

# A test to print 1st sub-array works. I know 'x' is a valid sub-array.
x = s[0]
x.each { |y| puts y }
puts

# This breaks down sub-arrays and prints each element on its own line.
#   Not what was wanted.
for i in 0..2
  x = s[i]
  puts x
end
puts

# Print all 3 sub-arrays as sub-arrays works. Could it be 'puts' pulls
#   arrays apart but 'print' does not?
for i in 0..2
  x = s[i]
  print "#{x}\n"
end
puts

# This works as expected, printing sub-arrays.
s.each { |x| print "#{x}\n" }
puts

# This works as expected, printing sub-arrays. So it's 'puts' on a
#   raw variable that breaks down the variable. Wrapping the variable
#   leaves it in sub-array form.
s.each { |x| puts "#{x}" }
puts

# This works as expected; 'print' on a raw variable does not break
#   it down. However 2 'print's are required. 'print x + "\n"' throws
#   an error. Semicolon required.
s.each { |x| print x; print "\n" }
puts

# Rewrite of above code to eliminate semicolon.
s.each do |x|
  print x
  print "\n"
end
puts

# Back to .each and what CodeCademy probably wanted...
# And it works perfectly: s is 2D array, x is 1D sub-array, y is
#   string.
s.each do |x|
  x.each do |y|
    print "#{y}\n"
  end
end
puts

# When using 'puts' variable must be wrapped. Although you'd
#   never realize it with this code ('puts y' will give same output).
s.each do |x|
  x.each do |y|
    puts "#{y}"
  end
end
puts

# Just for fun, and proof of my findings, the following breaks
#   down the 2D array 's' and prints each element on its own line.
puts s

CodeCademy, if you want people to get the lesson, tell them to use 'print' and not 'puts'.