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:

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

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

David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

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

[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?

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 :slight_smile:

···

--
Alex

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

···

On 8/8/07, FireAphis <FireAphis@gmail.com> 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

[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

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

Weird, I just blogged about this topic: http://drewolson.wordpress.com/\.

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

class Array
  def adjacent_pairs
    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:

irb(main):012:0> [1,2,3,4].adjacent_pairs
=> [[1, 2], [2, 3], [3, 4]]
irb(main):013:0> [1,2,3,4].adjacent_pairs do |a,b|
irb(main):014:1* puts "#{a} #{b}"
irb(main):015:1> end
1 2
2 3
3 4
=> [[1, 2], [2, 3], [3, 4]]

···

--
Posted via http://www.ruby-forum.com/\.

dblack@rubypal.com wrote:

Hi --

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

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

Oh, that's neat :slight_smile:

···

On Wed, 8 Aug 2007, FireAphis wrote:

--
Alex

Sorry Enumerable#each_cons(n) { }

you might need to require 'enumerable' though.

···

On 8/8/07, Jano Svitok <jan.svitok@gmail.com> wrote:

On 8/8/07, FireAphis <FireAphis@gmail.com> 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
>
> [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

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

Hi --

···

On Wed, 8 Aug 2007, Jano Svitok wrote:

On 8/8/07, FireAphis <FireAphis@gmail.com> 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

[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

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

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Short and elegant!

···

On Aug 8, 4:43 pm, dbl...@rubypal.com wrote:

Hi --

On Wed, 8 Aug 2007, 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

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

> 12
> 23
> 34
> 45

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

David

--
* Books:
   RAILS ROUTING (new!http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

require 'labrador/enum'
a.zip(a.map.succ).map.join.first(-1)

but the version with first is not released yet :frowning:

Robert

···

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

Hi --

···

On Wed, 8 Aug 2007, Robert Dober wrote:

require 'labrador/enum'
a.zip(a.map.succ).map.join.first(-1)

but the version with first is not released yet :frowning:

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.... :slight_smile: (And I honestly
can't puzzle it out.)

David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

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 :wink:

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 8/8/07, dblack@rubypal.com <dblack@rubypal.com> wrote:

Hi --

On Wed, 8 Aug 2007, Robert Dober wrote:

> require 'labrador/enum'
> a.zip(a.map.succ).map.join.first(-1)

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

Thanks everybody for help and plethora of solution ideas you've been
very helpful.

Thanks again
FireAphis

···

On Aug 8, 5:35 pm, "Robert Dober" <robert.do...@gmail.com> wrote:

On 8/8/07, dbl...@rubypal.com <dbl...@rubypal.com> wrote:> Hi --

> On Wed, 8 Aug 2007, Robert Dober wrote:

> > require 'labrador/enum'
> > 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 :wink:

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

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