Array.do Confusion

Hi everyone,

I’m feeling a bit surprised with the results that I’m getting from .do while attempting to do something basic.

I have a multidimensional array, and when using the .do method I expect to get each subarray. However, I’m getting quite different results. Can someone please explain why.

z = [[1, [100, 110]], [2, [200, 220]], [3, [300, 330]]];

z.do { |array, i| array[i].postln };

When I run the do loop, I expect to get:

[ 1, [ 100, 110 ] ]
[ 2, [ 200, 220 ] ]
[ 3, [ 300, 330 ] ]
-> [ [ 1, [ 100, 110 ] ], [ 2, [ 200, 220 ] ], [ 3, [ 300, 330 ] ] ]

However what I actually see post is:

1
[ 200, 220 ]
nil
-> [ [ 1, [ 100, 110 ] ], [ 2, [ 200, 220 ] ], [ 3, [ 300, 330 ] ] ]

What gives?

Thanks!

You have mistaken the arguments to the function. Here is a better description.

z = [[1, [100, 110]], [2, [200, 220]], [3, [300, 330]]];
z.do { |item, indexOfItem| ... };

// e.g.....

z.do { |item, indexOfItem| 
	"current item is \"%\", the item's index is \"%\""
    .format(item, indexOfItem).postln 
};
//
current item is "[ 1, [ 100, 110 ] ]", the item's index is "0"
current item is "[ 2, [ 200, 220 ] ]", the item's index is "1"
current item is "[ 3, [ 300, 330 ] ]", the item's index is "2"

do could also be called foreachitem.

So when you try to access [3, [300, 330]] at it’s third index, you get nil, because it is out of bounds. In other words…

z.collect({ |item, indexOfItem| 
	item == z[indexOfItem]
});

Ahh, right.

The real thing I was trying to do was to retrieve the first entry of each subarray, so when that didn’t initially work, I got turned around. :person_facepalming:

Instead of z.do { |array, i| array[i].postln }; I should have written z.do { |array, i| array[0].postln };.

Thanks Jordan!

If you want the first element of each sub array, try this,

z.collect(_.first)
1 Like

Oh nice!

.first and .last will both be useful for what I’m trying to do, and much simpler to write out.

Thanks again!