# Iterating list in pairs

Hello,

I need to iterate through a list and handle two elements on every
iteration. That is I’d like to do something like

[1,2,3,4,5].each { |x, y| puts x.to_s + y.to_s }

12
23
34
45

This code doesn’t work off course.
I can iterate using indices

0.upto(list.size-1) { |i| puts list[i] + list[i+1] }

But it looks ugly to me. Do you know any elegant tricks that don’t use
list indices?

Thanks
FireAphis

Hi –

On Wed, 8 Aug 2007, FireAphis wrote:

45
[1,2,3,4,5].inject {|a,b| puts “#{a}#{b}”; b }

David

FireAphis wrote:

45

This code doesn’t work off course.
I can iterate using indices

0.upto(list.size-1) { |i| puts list[i] + list[i+1] }

But it looks ugly to me. Do you know any elegant tricks that don’t use
list indices?
irb(main):001:0> a = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):002:0> a[0,4].zip(a[1,5]).each{|x,y| puts x.to_s + y.to_s}
12
23
34
45
=> [[1, 2], [2, 3], [3, 4], [4, 5]]

Unless a[0,4] breaks your “no list indices” rule, of course

On 8/8/07, FireAphis [email protected] wrote:

45
FireAphis
Enumerable#each_slice(n) {|…| …}

[email protected] wrote:

12
23
34
45

[1,2,3,4,5].inject {|a,b| puts “#{a}#{b}”; b }

Oh, that’s neat

On 8/8/07, Jano S. [email protected] wrote:

34
Thanks
FireAphis

Enumerable#each_slice(n) {|…| …}

Sorry Enumerable#each_cons(n) { }

you might need to require ‘enumerable’ though.

a.zip(a.map.succ).map.join.first(-1)

but the version with first is not released yet

Robert

Hi –

On Wed, 8 Aug 2007, Jano S. wrote:

34
Thanks
FireAphis

Enumerable#each_slice(n) {|…| …}

That won’t work because it won’t double back; you’ll get 12, 34, 5
instead of 12, 23, 34, 45.

However, you reminded me of something:

require ‘enumerator’
[1,2,3,4,5].enum_cons(2).each {|a,b| puts “#{a}#{b}” }

David

Hi –

On Wed, 8 Aug 2007, Robert D. wrote:

a.zip(a.map.succ).map.join.first(-1)

but the version with first is not released yet

I can’t quite follow how that will get to the result. Can you walk me
through it? My first reaction is that it’s awfully full of “magic
dots”, but I’m willing to be enlightened… (And I honestly
can’t puzzle it out.)

David

On 8/8/07, [email protected] [email protected] wrote:

Hi –

On Wed, 8 Aug 2007, Robert D. wrote:

a.zip(a.map.succ).map.join.first(-1)
map without a parameter creates a Proxy object that contains the
enumeration and the method name :map.
It’s method_missing forwards everything to the enumeration via send
and the method name, thus
map.join becomes
map{|x| x.send(:join)}

it is not everybody’s cup of tea, but I love it, obviously.
Labrador, the LAZY programmers best friend

class EmptyProxy < EmptyObject
def initialize object, message
@enum = object
@message = message
end
end

class Dispatcher < EmptyProxy
def method_missing mth, *args, &blk
@enum.send(@message){|x| x.send(mth.to_sym,*args)}
end # def method_missing mth, *args, &blk
end # class Dispatcher < EmptyProxy

Cheers
Robert

On Aug 8, 4:43 pm, [email protected] wrote:

12
RAILS ROUTING (new!http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (Ruby for Rails)

Short and elegant!

On Aug 8, 5:35 pm, “Robert D.” [email protected] wrote:

and the method name, thus
end

[…] as simple as possible, but no simpler.
– Attributed to Albert Einstein

Thanks everybody for help and plethora of solution ideas you’ve been

Thanks again
FireAphis

FireAphis wrote:

Hello,

I need to iterate through a list and handle two elements on every
iteration. That is I’d like to do something like

I did it using the zip method, something like this (I added block
handling to this example):

class Array
if block_given?
self[0…-2].zip(self[1…-1]).each do |a,b|
yield a,b
end
else
self[0…-2].zip(self[1…-1])
end
end
end

Now we can do either of the following: