How to read arrary with an array

Hello. I believe this is basic question, but I’m just starting to learn
programming and choose Ruby to learn from. I grabbed Chris P.'s book
Learn to Program to read, try, and learn from.

Anyway, the book had a lesson on creating a table contents using arrays.
Below is his less advance solution he gave. For the most part I get it.
The problem, I don’t understand how to read the arrary within an array,
or more how the pc reads it. I think that also leads to why I don’t
understand the variables being created later as well.

I tried looking around here, and google, but I’m getting results beyond
the lesson and my understanding. Below is the program and my notes.

Thanks in advance–Rich.

table of contents using arrays

title = ‘Table of Contents’

chapters = [[‘Getting Started’, 1], [‘Numbers’, 9], [‘Letters’, 13]]

array within an array.

don’t understand how to read

puts title.center(50)
puts
chap_num = 1

chapters.each do |chap|
name = chap[0] # don’t undestand chap [0] and chap [1] reference
page = chap[1] # assuming where in master array to pull data

beginning = 'Chapter ’ + chap_num.to_s + ': ’ + name
ending = 'page ’ + page.to_s

puts beginning.ljust(30) + ending.rjust(20)
chap_num = chap_num + 1
end

don’t undestand chap [0] and chap [1] reference

If you are confused, it is the author’s fault for choosing confusing
variable names. If the variable names were descriptive, the code would
be self explanatory.

colors = [‘red’, ‘black’, ‘yellow’]

colors.each do |color|
puts “The current color is: #{color}”
end

–output:–
The current color is: red
The current color is: black
The current color is: yellow

array_of_arrays = [
[10, 20, 30],
[‘a’, ‘b’, ‘c’, ‘d’],
[‘hello’, ‘goodbye’]
]

array_of_arrays.each do |sub_array|
p sub_array
end

–output:–
[10, 20, 30]
[“a”, “b”, “c”, “d”]
[“hello”, “goodbye”]

array_of_arrays.each do |sub_array|
puts sub_array[0]
end

–output:–
10
a
hello

array_of_arrays.each do |chapter|
puts chapter[0]
end

–output:–
10
a
hello

zebras = [
[10, 20, 30],
[‘a’, ‘b’, ‘c’, ‘d’],
[‘hello’, ‘goodbye’]
]

zebras.each do |elephant|
p elephant[0]
end

–output:–
10
“a”
“hello”

If you are confused about what is contained in a variable, go ahead and
print it out, e.g.

zebras.each do |elephant| #what the #@$#@ is elephant referring to??
p elephant #add this line to see what the heck elephant is all about
p elephant[0]
end

Arrays can contain a mix of different data types:

data = [
[‘red’, ‘white’, ‘blue’], #array type
‘hello’, #string type
10 #integer type
]

data.each do |array_element|
p array_element
end

–output:–
[“red”, “white”, “blue”]
“hello”
10

The elements of an array are separated by commas–that’s how you know
when one element ends and another begins.

In this case it’s pretty simple, if you rearrange the source code you
can get a hint at how to read it:

chapters = [
  [ 'Getting Started',  1 ],
  [ 'Numbers',          9 ],
  [ 'Letters',         13 ]
]

The ‘chapters’ variable itself is a flat list of things; think of
those things as “rows”. Each row is itself a list, of “columns”.
So chapters[1][0] can be pronounced “chapters, row 1, column 0”, which
in this case is the String ‘Numbers’.

This way of thinking about it, and laying it out, will work as long as
there are only two levels of arrays, and the inner arrays are all of
the same length. For deeper nestings you’ll have to come up with your
own way of visualising, but the same idea – of accessing a single
element, and then accessing an element inside it – still holds.

On 2 October 2012 12:19, Richard D. [email protected] wrote:

I tried looking around here, and google, but I’m getting results beyond

don’t understand how to read

beginning = 'Chapter ’ + chap_num.to_s + ': ’ + name
ending = 'page ’ + page.to_s

puts beginning.ljust(30) + ending.rjust(20)
chap_num = chap_num + 1
end


Posted via http://www.ruby-forum.com/.


Matthew K., B.Sc (CompSci) (Hons)
http://matthew.kerwin.net.au/
ABN: 59-013-727-651

“You’ll never find a programming language that frees
you from the burden of clarifying your ideas.” - xkcd

Thanks for replies. I at least understand it much better between the
two posts and understand the code for the program.

So confirm my basic understanding, basically in this case the each inner
array would be a row, and each item would fall into some kind of column,
to use a spread sheet reference. So it would read
col 1, col2
row1 Getting, 1
row2 Numbers, 9
row3 Letters, 13.

Later the author just made the variables to reference just the columns;
name: go to first column
page: go to second column.

The author explained that an array is just a set of data. He just
didn’t explain how an array within an array worked, but briefly showed
it existed.

Again, thanks for the help.

Am 02.10.2012 05:37, schrieb 7stud --:

don’t undestand chap [0] and chap [1] reference

If you are confused, it is the author’s fault for choosing confusing
variable names. If the variable names were descriptive, the code would
be self explanatory.

I disagree.

In my opinion chapters.each { |chap| ... } is perfectly alright
for the given example. I really see no difference to your colors
example and it’s a lot more descriptive than the rather data structure
centered array_of_arrays.each { |sub_array| ... }.

I’m pretty sure you would not recommend using variable names like
text, some_hash, my_hash, or array_of_strings?!

On Tue, Oct 2, 2012 at 9:50 AM, Richard D. [email protected] wrote:

Thanks for replies. I at least understand it much better between the
two posts and understand the code for the program.

So confirm my basic understanding, basically in this case the each inner
array would be a row, and each item would fall into some kind of column,
to use a spread sheet reference. So it would read
col 1, col2
row1 Getting, 1
row2 Numbers, 9
row3 Letters, 13.

Basically yes, just the indices start with 0. So an array with three
elements will have elements at 0, 1 and 2.

Later the author just made the variables to reference just the columns;
name: go to first column
page: go to second column.

The author explained that an array is just a set of data. He just
didn’t explain how an array within an array worked, but briefly showed
it existed.

You just need to know that when you access a position of an array, it
returns whatever object sits there. It could be another array:

array_of_arrays = [ [1,2,3], [4,5,6]]

first_array = array_of_arrays[0] # get the object that sits at the
first position of the array

Now, first_array is another array, that behaves the same.

Jesus.

after some experimenting, I understand but still have a bit of fog.
Basically, the idea was to see how data would be pulled from slight
different arrays. But I’m getting two completely different results. I
was expecting to be the same, except my “=====” break to tell the
different outputs.

program 1

array1 = [[‘a’,‘b’],[1, 2],[‘x’,‘y’]]
array2 = [‘a’,[1,2],‘x’]

array1.each do |ray|
test1 = ray[0]
puts test1
end
puts ‘=======’

array1.each do |ray|
test2 = ray[1]
puts test2
end
puts ‘=======’
array2.each do |ray2|
test3 = ray2[0]
puts test3
end
puts ‘=====’
array2.each do |ray2|
test4 = ray2[1]
puts test4
end
puts ‘=====’
puts array1[0].to_s + ’ ’ + array2[0].to_s
puts
puts array1[1].to_s + ’ ’ + array2[1].to_s
puts
puts array1[2].to_s + ’ ’ + array2[2].to_s

OUTPUT
a
1
x

b
2
y

a
1
x

2

=====
[“a”,“b”] a

[1, 2] [1, 2]

[“x”, “y”] x

Program 2

{same as above, excpet)
array1.each do |ray|
test1 = ray[0]
test2 = ray[1]
puts test1
puts ‘
puts test2
end
puts ‘=======’
array2.each do |ray2|
test3 = ray2[0]
test4 = ray2[1]
puts test3
puts '

puts test4
end

OUTPUT
a


b
1


2
x


y

a


1


2
x


======
[“a”,“b”] a

[1, 2] [1, 2]

[“x”, “y”] x

So I think I got what the arrays do. I just don’t think I’m
understanding how things are being located. What I"m thinking is this
array1 = [[‘a’,‘b’],[1, 2],[‘x’,‘y’]]
array1: a is slot0-0, b is slot0-1, 1 is slot1-0, 2 is slot 1-1, x is
slot2-0, and y is slot 2-1
array2 = [‘a’,[1,2],‘x’]
a is slot1-0-0, 1 is 1-0, 2 is 1-1, and x is 2-0

I thought in both programs the ray(x)[0] would output all x-0 slots, and
ray(x)[1] would out put all -1 slots

On Tue, Oct 2, 2012 at 5:35 PM, Richard D. [email protected] wrote:

puts ‘=======’
puts array1[0].to_s + ’ ’ + array2[0].to_s
b

test1 = ray[0]
puts ‘****’
x


array1 = [[‘a’,‘b’],[1, 2],[‘x’,‘y’]]
array1: a is slot0-0, b is slot0-1, 1 is slot1-0, 2 is slot 1-1, x is
slot2-0, and y is slot 2-1
array2 = [‘a’,[1,2],‘x’]
a is slot1-0-0, 1 is 1-0, 2 is 1-1, and x is 2-0

I thought in both programs the ray(x)[0] would output all x-0 slots, and
ray(x)[1] would out put all -1 slots

The reason is that your metaphor about arrays being like a 2x2 matrix
is wrong, specially in the cases where the contents of the array are
not arrays themselves. It’s better if you think of it this way:

array1 = [[‘a’,‘b’],[1, 2],[‘x’,‘y’]]

array1 is an array with three elements, with indexes 0, 1 and 2. At
index 0, there is an object, which happens to be another array. At
index 1 there is an object that happens to be another array. The same
for index 2. So:

first_array = array1[0]

first array is now [‘a’, ‘b’], which is an array. At position 0 there
is a String object, so first_array[0] => ‘a’. At position 1 there’s
another string, so first_array[1] => ‘b’

The confusion might come because you can “chain” method calls like this:

array1[0][0] #=> ‘a’

but in reality this are two different steps. First, method [] with
argument 0 is called on array1. This returns a different array. Then,
method [] with argument 0 is called on the returned array. This method
call returns a String, which is ‘a’.

When you move to array2, though, your assumptions break, because:

array2 = [‘a’, [1,2], ‘x’]

array2[0] calls method [] on the array, with argument 0, which returns
the first object of the array. It happens that in this case, this
object is not an array, but the string ‘a’. You have the object
directly when you do that. This is not a 2x2 array. It’s just an array
in which the second element is itself an array, but that’s not the
case for the first or third objects, which are just strings. So:

array2[0] => ‘a’, a String

If you do

array2[0][0], this calls method [] with argument 0 of the array,
returning a String. You then call method [] with argument 0 of the
String (yes, String also has a method [], which returns a section of
the string), in this case returning ‘a’, because you asked for the
first character of the String.

Later in the code, you do array2[0][1], which is thus calling the
method [] with argument 1 on the string ‘a’, which is asking the
string for the second character, which doesn’t exist, and so you get
nil (empty when puts’ed).

You should play a little bit in irb to see the different steps.

Jesus.

Am 02.10.2012 09:50, schrieb Richard D.:

So confirm my basic understanding, basically in this case the each inner
array would be a row, and each item would fall into some kind of column,
to use a spread sheet reference. So it would read
col 1, col2
row1 Getting, 1
row2 Numbers, 9
row3 Letters, 13.

In this case you can interpret the nested arrays in this way.
But that’s not a general rule for arrays.
You could also consider an array that contains several columns,
where each column has a couple of rows. That really depends on
how you want to look at your data.

The author explained that an array is just a set of data. He just
didn’t explain how an array within an array worked, but briefly showed
it existed.

Well, he explaines at the start of chapter 8 that each “slot” is
simply pointing to some object (which can be anything).
And there is nothing special about “how an array within an array works”.

This is an array:

objects = [5, [‘a’, ‘b’], Time.new]

It’s first element objects[0] is 5 and objects[1] is the
array [‘a’, ‘b’].

unknown wrote in post #1078384:

Some (but not all) of the objects in the array
have a slice-method for element reference, aka []:

“slice” is not an alias for “[]”. What makes you think that?

I do not understand what your problem is.

array = [‘abc’, [1, 2], 3.0, Time.new]

You can iterate through the elements (or “slots”)

array.each do |element|
puts element.inspect
end

=>
“abc”
[1, 2]
3.0
2012-10-02 18:09:14 +0200

Some (but not all) of the objects in the array
have a slice-method for element reference, aka []:

array.each do |element|
puts element[0] if element.respond_to?(:slice)
end

=>
a
1

Am 02.10.2012 19:44, schrieb Jan E.:

unknown wrote in post #1078384:

Some (but not all) of the objects in the array
have a slice-method for element reference, aka []:

“slice” is not an alias for “[]”. What makes you think that?

Maybe only for String and Array.

But the code should of course be:

array.each do |element|
puts element[0] if element.respond_to?(:[])
end

thanks for the replies, especially the thorough one from Jesus. What
you explained was what I was thinking. I was expecting nil outputs.

What I can’t seem to figure out is how come I’m getting outputs between
these codes:

array1 = [[‘a’,‘b’],[1, 2],[‘x’,‘y’]]

array1.each do |ray|
puts ray[0] #output a1x (expected and wanted)
end

puts “=======”

array1.each do |ray|
puts ray[1] #output b2y (expected and wanted)
end

puts “=======” #versus#

array1.each do |ray| #four outputs of a, b1, 2x, y
puts ray[0]
puts ‘****’
puts ray[1]
end

I was assuming I would get the same outcome. I’m not seeing difference
other than being repeative between the two codes paragraphs(?). I
suspect my lack of understanding my lie

It should be noted, I’m not far enough in the book to have blocks
explained, so are this point, in how it used, it’s more a way to turn a
method output into a variable, with will do something later. I know
it’s probably completely wrong. I’m on chapter 8 and I believe, blocs
and procs are chapter 14. I literally started a week ago. And my
experience of any kind of programming was more scripting for basic HTML
(I believe version 2, whatever it was back in 1998) and bat files for
DOS 6.22 that just made a nice interface to call up programs, which was
around 1995/6.

On a side note, I have not a clue of what slice is or what it does or
does not do.

Lastly, thanks for your patience in my learning process.

array2 = [‘a’,[1,2],‘x’]
a is slot1-0-0, 1 is 1-0, 2 is 1-1, and x is 2-0

No. Your array has 3 elements (remember commas separate the elements of
an array)

The first element of your array is at index position 0, and it is the
string ‘a’.
The second element of your array is at index position 1, and it is the
array [1, 2]
The third element of your array is at index position 2, and it is the
string ‘x’.

Once you get a reference to any of those items, you can do whatever that
item’s class allows you to do to the item. So for instance, for either
of the strings you can call the capitalize() method–but you can’t call
capitalize() on the array.

Where you seem to be confused is that the String class also allows you
to call the method [] on a String, so a String acts like an array in
that respect. As a result, you can do this:

data = [
‘hello’,
‘world’
]

data.each do |string|
puts string
puts string[2]
end

–output:–
hello
l
world
r

But look what happens here:

string = ‘a’
p string[1]

–output:–
nil

That’s because the String only has a character at position 0, and
position 1 is beyond the end of the String.

#four outputs of a, b1, 2x, y

No. Your output is:

a


b

1


2

x


y

…which is three sets of output corresponding to your three arrays.
You succeeded in confusing yourself with your output format. This would
have been better:

puts “=======” #versus#

array1.each do |ray|
puts ray[0]
puts ray[1]
puts ‘***’
end

–output:–

=======
a
b


1
2


x
y


Or even:

puts “=======” #versus#

array1.each do |ray| #four outputs of a, b1, 2x, y
puts “#{ray[0]} *** #{ray[1]}”
end

–output:–

a *** b
1 *** 2
x *** y

OH!!! Now I see. I was not thinking correctly the puts statments

array1.each do |ray|
puts ray[0]
puts ‘****’
puts ray[1]
end

I was thinking the output was going to be all three ray[0], then the
stars, than all three ray[1]. It’s a good rookie mistake. Hopefully I
don’t do that anytime soon. I’m laughing because it was so obvious if I
had been thinking.

Thanks for the help and clarifying that to me. Much appreciated.

Am 02.10.2012 20:44, schrieb Richard D.:

array1.each do |ray| #four outputs of a, b1, 2x, y
puts ray[0]
puts ‘****’
puts ray[1]
end

I was assuming I would get the same outcome.

Well, that’s wrong. You did not understand how Array#each works.

Each array element is passed to the variable ray and then
the complete block is evaluated for that single element,
then the next element is passed to ray etc.
Array#each does not evaluate each line for all array elements
and then go to the next line.

It should be noted, I’m not far enough in the book to have blocks
explained, so are this point, in how it used, it’s more a way to turn a
method output into a variable, with will do something later.

No, you misunderstood what the author is saying.
But at the moment you do not have to understand more about blocks
than that they here behave similar to the block of a while loop.

Array#each is explained in detail in chapter 8.1, please reread.

On a side note, I have not a clue of what slice is or what it does or
does not do.

I just wanted to point out that an array that contains an array is not a
2x2 matrix with rows and columns, and also can contain objects that
do not even have an element reference (so that object[3] is not
possible and gives a syntax error).

For some reason, despite the examples, I was making a connection that
this working like a loop. 7stud’s reply wake me up.

Nonetheless, thanks for everyone’s help.

On Tue, Oct 2, 2012 at 8:44 PM, Richard D. [email protected] wrote:

end
puts ray[0]
puts ‘****’
puts ray[1]
end

I was assuming I would get the same outcome. I’m not seeing difference
other than being repeative between the two codes paragraphs(?). I
suspect my lack of understanding my lie

I’m not really sure what you expected in the third case, but let’s see
step by step what this does. The method each iterates over your array,
passing each element in turn to the block. For example:

array = [1,2,3]
array.each do |element|
p element
end

This iterates over the array passing 1, then 2, then 3 to the block.
The block receives that value in the element variable, which is just
printed.

array1 = [[‘a’,‘b’],[1, 2],[‘x’,‘y’]]
array1.each do |ray|
p ray
puts ray[0]
puts ‘****’
puts ray[1]
end

In this case, the array has 3 elements. Each time around the loop the
“ray” variable will contain one of the elements. The first time, ray
will be [‘a’,‘b’]. So when you print ray[0] it prints ‘a’ and when you
print ray[1] it prints ‘b’. The second time, ray will be [1,2]. The
third time, ray will be [‘x’,‘y’].

This explains the behaviour you see.

Jesus.