Iterating over an array n element at a time

Is there an elegant way to iterate over an array n elements at a time?
e.g. something like...

a = [1,1,1,2,2,2,3,3,3]

a.each(3) do |x,y,z|
    print x,y,z,"\n"
end

prints...
111
222
333

//kim

harp:~ > ruby -r enumerator -e' %w( 1 2 3 4 5 ).each_slice(2){|slice| p slice} '
["1", "2"]
["3", "4"]
["5"]

harp:~ > ruby -r enumerator -e' %w( 1 2 3 4 5 ).each_cons(2){|slice| p slice} '
["1", "2"]
["2", "3"]
["3", "4"]
["4", "5"]

-a

···

On Sun, 6 Aug 2006, Kim Pedersen wrote:

Is there an elegant way to iterate over an array n elements at a time?
e.g. something like...

a = [1,1,1,2,2,2,3,3,3]

a.each(3) do |x,y,z|
  print x,y,z,"\n"
end

prints...
111
222
333

//kim

--
happiness is not something ready-made. it comes from your own actions.
- h.h. the 14th dali lama

require 'enumerator'
[1,1,1,2,2,2,3,3,3].each_slice(3){|a,b,c|p [a,b,c]}

j`ey
http://www.eachmapinject.com

···

On 8/5/06, Kim Pedersen <kimersen@online.no> wrote:

Is there an elegant way to iterate over an array n elements at a time?
e.g. something like...

a = [1,1,1,2,2,2,3,3,3]

a.each(3) do |x,y,z|
    print x,y,z,"\n"
end

prints...
111
222
333

//kim

Kim Pedersen wrote:

Is there an elegant way to iterate over an array n elements at a time?
e.g. something like...

a = [1,1,1,2,2,2,3,3,3]

a.each(3) do |x,y,z|
    print x,y,z,"\n"
end

prints...
111
222
333

//kim

enumerator is probably better since it is built-in, but...

  require 'facet/enumerable/each_by'
  a = [1,1,1,2,2,2,3,3,3]
  a.each_by(3) { |x,y,z| print x,y,z,"\n" }
  111
  222
  333

But why not have Ruby fill those arguments out automatically? This
already does:

  a = [[1,1,1],[2,2,2],[3,3,3]]
  a.each { |x,y,z| print x,y,z,"\n" }

So couldn't some "slurping" indicator be used?

  a = [1,1,1,2,2,2,3,3,3]
  a.each { |(x,y,z)| print x,y,z,"\n" }

Or something.

T.

Kim Pedersen wrote:

Is there an elegant way to iterate over an array n elements at a time?
e.g. something like...

a = [1,1,1,2,2,2,3,3,3]

a.each(3) do |x,y,z|
    print x,y,z,"\n"
end

prints...
111
222
333

//kim

enumerator is probably better since it is built-in, but...

  require 'facet/enumerable/each_by'
  a = [1,1,1,2,2,2,3,3,3]
  a.each_by(3) { |x,y,z| print x,y,z,"\n" }
  111
  222
  333

But why not have Ruby fill those arguments out automatically? This
already does:

  a = [[1,1,1],[2,2,2],[3,3,3]]
  a.each { |x,y,z| print x,y,z,"\n" }

So couldn't some "slurping" indicator be used?

  a = [1,1,1,2,2,2,3,3,3]
  a.each { |(x,y,z)| print x,y,z,"\n" }

Or something.

( ) already have meaning in block arguments though
e.g.:

{ :a => 1, :b => 2 }.inject({}) { |h, (k, v)| h[k] = v + 1; h }
#=> {:b=>3, :a=>2}

···

On Aug 5, 2006, at 3:20 PM, Trans wrote:

T.

Trans wrote:

Kim Pedersen wrote:
  

Is there an elegant way to iterate over an array n elements at a time?
e.g. something like...

a = [1,1,1,2,2,2,3,3,3]

a.each(3) do |x,y,z|
    print x,y,z,"\n"
end

prints...
111
222
333

//kim
    
enumerator is probably better since it is built-in, but...

  require 'facet/enumerable/each_by'
  a = [1,1,1,2,2,2,3,3,3]
  a.each_by(3) { |x,y,z| print x,y,z,"\n" }
  111
  222
  333

But why not have Ruby fill those arguments out automatically? This
already does:

  a = [[1,1,1],[2,2,2],[3,3,3]]
  a.each { |x,y,z| print x,y,z,"\n" }

So couldn't some "slurping" indicator be used?

  a = [1,1,1,2,2,2,3,3,3]
  a.each { |(x,y,z)| print x,y,z,"\n" }

Or something.

T.
  

I think I'd recast the array as a matrix and then iterate over rows (or columns, depending on which way you did the recast).

require 'enumerator'

module Enumerable
  def eachn(&block)
    n = block.arity
    each_slice(n) {|i| block.call(*i)}
  end
end

a = (1..10).to_a
a.eachn {|x,y,z| p [x,y,z]}

martin

···

On 8/6/06, Trans <transfire@gmail.com> wrote:

But why not have Ruby fill those arguments out automatically? This
already does:

  a = [[1,1,1],[2,2,2],[3,3,3]]
  a.each { |x,y,z| print x,y,z,"\n" }

So couldn't some "slurping" indicator be used?

  a = [1,1,1,2,2,2,3,3,3]
  a.each { |(x,y,z)| print x,y,z,"\n" }

Or something.

Trans wrote:

Kim Pedersen wrote:

Is there an elegant way to iterate over an array n elements at a time?
e.g. something like...

a = [1,1,1,2,2,2,3,3,3]

a.each(3) do |x,y,z|
    print x,y,z,"\n"
end

prints...
111
222
333

//kim

enumerator is probably better since it is built-in, but...

  require 'facet/enumerable/each_by'
  a = [1,1,1,2,2,2,3,3,3]
  a.each_by(3) { |x,y,z| print x,y,z,"\n" }
  111
  222
  333

But why not have Ruby fill those arguments out automatically? This
already does:

  a = [[1,1,1],[2,2,2],[3,3,3]]
  a.each { |x,y,z| print x,y,z,"\n" }

So couldn't some "slurping" indicator be used?

  a = [1,1,1,2,2,2,3,3,3]
  a.each { |(x,y,z)| print x,y,z,"\n" }

Or something.

T.

Note though that your code does something different than each_cons which moves a sliding window while your code iterates in chunks! See:

robert@fussel ~
$ ruby -r enumerator -e' %w( 1 2 3 4 5 ).each_cons(2){|a, b| p a, b, "-"} '
"1"
"2"
"-"
"2"
"3"
"-"
"3"
"4"
"-"
"4"
"5"
"-"

robert@fussel ~
$

Kind regards

  robert

Logan Capaldo wrote:

( ) already have meaning in block arguments though
e.g.:

{ :a => 1, :b => 2 }.inject({}) { |h, (k, v)| h[k] = v + 1; h }
#=> {:b=>3, :a=>2}

Right, but it seems to be similar in nature. Could it not be used for
both?

Otherwise another notation

  { |[x,y,z]| ... }

perhaps.

T.

Nice! As it turns out that *i in the block.call invocation isn't
needed. The proc call method does the right thing in this case.

Also there's no need to turn the range into an array, it'll work
directly since ranges mixin Enumerable

···

On 8/5/06, Martin DeMello <martindemello@gmail.com> wrote:

On 8/6/06, Trans <transfire@gmail.com> wrote:
> But why not have Ruby fill those arguments out automatically? This
> already does:
>
> a = [[1,1,1],[2,2,2],[3,3,3]]
> a.each { |x,y,z| print x,y,z,"\n" }
>
> So couldn't some "slurping" indicator be used?
>
> a = [1,1,1,2,2,2,3,3,3]
> a.each { |(x,y,z)| print x,y,z,"\n" }
>
> Or something.

require 'enumerator'

module Enumerable
  def eachn(&block)
    n = block.arity
    each_slice(n) {|i| block.call(*i)}
  end
end

a = (1..10).to_a
a.eachn {|x,y,z| p [x,y,z]}

--
Rick DeNatale

Robert Klemme wrote:

Trans wrote:
> Kim Pedersen wrote:
>> Is there an elegant way to iterate over an array n elements at a time?
>> e.g. something like...
>>
>> a = [1,1,1,2,2,2,3,3,3]
>>
>> a.each(3) do |x,y,z|
>> print x,y,z,"\n"
>> end
>>
>> prints...
>> 111
>> 222
>> 333
>>
>> //kim
>
> enumerator is probably better since it is built-in, but...
>
> require 'facet/enumerable/each_by'
> a = [1,1,1,2,2,2,3,3,3]
> a.each_by(3) { |x,y,z| print x,y,z,"\n" }
> 111
> 222
> 333
>
> But why not have Ruby fill those arguments out automatically? This
> already does:
>
> a = [[1,1,1],[2,2,2],[3,3,3]]
> a.each { |x,y,z| print x,y,z,"\n" }
>
> So couldn't some "slurping" indicator be used?
>
> a = [1,1,1,2,2,2,3,3,3]
> a.each { |(x,y,z)| print x,y,z,"\n" }
>
> Or something.
>
> T.
>
>
Note though that your code does something different than each_cons which
moves a sliding window while your code iterates in chunks! See:

Right. But wasn't that what was originally asked for? In any case, I
am only meaning the "chunk" case with my example, but certainly one
could conceive of a notion to "slide" too. The advantage of notation
over more methods is that it works with derivatives. Eg. pseudo code:

  [1,1,2,2,3,4].select { |slide(a,b)| a == b }

Otherwise you need a select_slice, select_cons, collect_slice,
collect_cons, and so on.

T.

Hi,

At Sun, 6 Aug 2006 19:55:37 +0900,
Trans wrote in [ruby-talk:206591]:

  [1,1,2,2,3,4].select { |slide(a,b)| a == b }

Otherwise you need a select_slice, select_cons, collect_slice,
collect_cons, and so on.

Longer a little, but it's possible with enumerator.

  [1,1,2,2,3,4].enum_cons(2).select {|a, b| a == b}

···

--
Nobu Nakada

Just a tiny little trap you fell into, look at this
[1,2,3].each_slice(2){|s| p s}
NoMethodError: undefined method `each_slice' for [1, 2, 3]:Array
       from (irb):1

but

irb(main):003:0> require 'enumerator'
=> true
irb(main):004:0> [1,2,3].each_slice(2){|s| p s}
[1, 2]
[3]

I have fallen into that one more than once and I still will, it is a little
bit unclear why Enumerable is not in the core while it is in the core doc.
But well just a minor hickup.

Cheers
Robert
[SNIP]

···

On 8/6/06, Marcelo Alvim <malvim@gmail.com> wrote:

Hi,

Sorry about the real newbie interrupting the high level thread, but...

I liked very much the "eachn" method from Martin, and decided to test
it out. I got a "Undefined method 'each_slice'" for the array. Went to
ruby-doc.org, and the core docs have each_slice defined in module
Enumerable. I have Ruby 1.8.4 installed. Does anyone know why is that
not working for me?

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

You need to require 'enumerator', which adds additional methods like
each_slice to Enumerable.

martin

···

On 8/7/06, Marcelo Alvim <malvim@gmail.com> wrote:

Hi,

Sorry about the real newbie interrupting the high level thread, but...

I liked very much the "eachn" method from Martin, and decided to test
it out. I got a "Undefined method 'each_slice'" for the array. Went to
ruby-doc.org, and the core docs have each_slice defined in module
Enumerable. I have Ruby 1.8.4 installed. Does anyone know why is that
not working for me?

Huh - you're right, block.call(i) works nicely without the splat. I
guess it's because the argument list 'picks apart' the array. Good
catch.

martin

···

On 8/6/06, Rick DeNatale <rick.denatale@gmail.com> wrote:

On 8/5/06, Martin DeMello <martindemello@gmail.com> wrote:
> require 'enumerator'
>
> module Enumerable
> def eachn(&block)
> n = block.arity
> each_slice(n) {|i| block.call(*i)}
> end
> end
>
> a = (1..10).to_a
> a.eachn {|x,y,z| p [x,y,z]}

Nice! As it turns out that *i in the block.call invocation isn't
needed. The proc call method does the right thing in this case.

Rick DeNatale wrote:

For Ruby, I think that Nakada-san's suggestion is a better way to
compose such functionality.

Yes, I agree. I had forgotten about that.

T.

Just a tiny little trap you fell into, look at this
[1,2,3].each_slice(2){|s| p s}
NoMethodError: undefined method `each_slice' for [1, 2, 3]:Array
       from (irb):1

but

irb(main):003:0> require 'enumerator'
=> true
irb(main):004:0> [1,2,3].each_slice(2){|s| p s}
[1, 2]
[3]

I have fallen into that one more than once and I still will, it is a little
bit unclear why Enumerable is not in the core while it is in the core doc.
But well just a minor hickup.

Oh, I see! Thanks for the pointer.

I thought Array mixed that in, so it should be defined for it. But
then again, I'm still getting used to modules, mixins and such. Been
too long in a Java-only world...

Thanks again,
Marcelo Alvim.

Array does mix Enumerable in. However, the core Enumerable module
doesn't include each_slice; that is provided by the 'enumerator'
library, which reopens Enumerable and adds some methods to it. Note
that enumerator is in the standard lib rather than in the core.

http://www.ruby-doc.org/stdlib/libdoc/enumerator/rdoc/index.html

martin

···

On 8/7/06, Marcelo Alvim <malvim@gmail.com> wrote:

> Just a tiny little trap you fell into, look at this
> [1,2,3].each_slice(2){|s| p s}
> NoMethodError: undefined method `each_slice' for [1, 2, 3]:Array
> from (irb):1
>
> but
>
> irb(main):003:0> require 'enumerator'
> => true
> irb(main):004:0> [1,2,3].each_slice(2){|s| p s}
> [1, 2]
> [3]
>
> I have fallen into that one more than once and I still will, it is a little
> bit unclear why Enumerable is not in the core while it is in the core doc.
> But well just a minor hickup.

Oh, I see! Thanks for the pointer.

I thought Array mixed that in, so it should be defined for it. But
then again, I'm still getting used to modules, mixins and such. Been
too long in a Java-only world...

Actually it is in both

http://www.ruby-doc.org/core/classes/Enumerable.html

James, might it not be a good idea to get it out of the Core Doc?

Robert

···

On 8/6/06, Martin DeMello <martindemello@gmail.com> wrote:

On 8/7/06, Marcelo Alvim <malvim@gmail.com> wrote:
[SNIP]

Array does mix Enumerable in. However, the core Enumerable module
doesn't include each_slice; that is provided by the 'enumerator'
library, which reopens Enumerable and adds some methods to it. Note
that enumerator is in the standard lib rather than in the core.

http://www.ruby-doc.org/stdlib/libdoc/enumerator/rdoc/index.html

martin

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein