neontapir
neontapir

Reputation: 4736

How do I iterate through a nested array without flattening its contents?

I have an array with pairs of numbers:

a = [[4, 6], [3, 0], [0, 0]]

When I do:

a.each do |x|
  puts x
done

I get a flattened set of values:

4
6
3
0
0
0

What I want is for the values to remain in pairs:

[4,6]
[3,0]
[0,0]

Ideally, I'd like to iterate with an Enumerator, because I'd like to make use of #peek during the loop processing.

I've found that:

e = a.each
loop do
  puts e.next
end

gives the same output as the flattened example above, with an additional nil at the end.

Is there a way to loop while preserve the grouping of the array in pairs?

Upvotes: 1

Views: 336

Answers (1)

Arup Rakshit
Arup Rakshit

Reputation: 118271

You just need to use p, rather puts. Read this p vs puts.

Kernel#puts just treats arrays as a special case. It loops over the items and prints one per line. I didn't read source, that's just my understanding. I just confirmed from source, and found my understanding is correct :-

 io_puts_ary(VALUE ary, VALUE out, int recur)
6814 {
6815     VALUE tmp;
6816     long i;
6817 
6818     if (recur) {
6819         tmp = rb_str_new2("[...]");
6820         rb_io_puts(1, &tmp, out);
6821         return Qtrue;
6822     }
6823     ary = rb_check_array_type(ary);
6824     if (NIL_P(ary)) return Qfalse;
6825     for (i=0; i<RARRAY_LEN(ary); i++) {
6826         tmp = RARRAY_AREF(ary, i);
6827         rb_io_puts(1, &tmp, out);
6828     }
6829     return Qtrue;
6830 }

rb_io_puts says -

Writes the given objects to ios as with IO#print. Writes a record separator (typically a newline) after any that do not already end with a newline sequence.If called with an array argument, writes each element on a new line.If called without arguments, outputs a single record separator.

Upvotes: 4

Related Questions