Hello. I believe this is basic question, but I'm just starting to learn programming and choose Ruby to learn from. I grabbed Chris Pine'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
on 2012-10-02 04:19
on 2012-10-02 05:10
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. <lists@ruby-forum.com> 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 Kerwin, 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
on 2012-10-02 05:37
> 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.
on 2012-10-02 09:50
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.
on 2012-10-02 10:02
On Tue, Oct 2, 2012 at 9:50 AM, Richard D. <lists@ruby-forum.com> 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.
on 2012-10-02 14:07
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 2012-10-02 14:33
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'].
on 2012-10-02 17:35
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 2012-10-02 17:57
On Tue, Oct 2, 2012 at 5:35 PM, Richard D. <lists@ruby-forum.com> 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.
on 2012-10-02 18:12
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
on 2012-10-02 19:42
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?
on 2012-10-02 20:17
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
on 2012-10-02 20:44
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.
on 2012-10-02 20:52
> 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.
on 2012-10-02 20:57
> #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
on 2012-10-02 21:35
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).
on 2012-10-02 21:40
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.
on 2012-10-03 09:20
On Tue, Oct 2, 2012 at 8:44 PM, Richard D. <lists@ruby-forum.com> 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.
on 2012-10-03 17:47
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.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.