Iterating list in pairs

Discussion in 'Ruby' started by FireAphis, Aug 8, 2007.

  1. FireAphis

    FireAphis Guest

    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 + list[i+1] }

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

    Thanks
    FireAphis
     
    FireAphis, Aug 8, 2007
    #1
    1. Advertising

  2. FireAphis

    Guest

    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)
     
    , Aug 8, 2007
    #2
    1. Advertising

  3. FireAphis

    Alex Young Guest

    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 + 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 :)

    --
    Alex
     
    Alex Young, Aug 8, 2007
    #3
  4. FireAphis

    Jano Svitok Guest

    On 8/8/07, 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 + 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) {|...| ...}
     
    Jano Svitok, Aug 8, 2007
    #4
  5. FireAphis

    Alex Young Guest

    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 }
    >

    Oh, that's neat :)

    --
    Alex
     
    Alex Young, Aug 8, 2007
    #5
  6. FireAphis

    Jano Svitok Guest

    On 8/8/07, Jano Svitok <> wrote:
    > On 8/8/07, 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 + 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) {|...| ...}
    >


    Sorry Enumerable#each_cons(n) { }

    you might need to require 'enumerable' though.
     
    Jano Svitok, Aug 8, 2007
    #6
  7. FireAphis

    Guest

    Hi --

    On Wed, 8 Aug 2007, Jano Svitok wrote:

    > On 8/8/07, 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 + 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)
     
    , Aug 8, 2007
    #7
  8. FireAphis

    Robert Dober Guest

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

    but the version with first is not released yet :(

    Robert

    --
    [...] as simple as possible, but no simpler.
    -- Attributed to Albert Einstein
     
    Robert Dober, Aug 8, 2007
    #8
  9. FireAphis

    Guest

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


    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

    --
    * 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)
     
    , Aug 8, 2007
    #9
  10. FireAphis

    Robert Dober Guest

    On 8/8/07, <> 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 ;)

    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
     
    Robert Dober, Aug 8, 2007
    #10
  11. FireAphis

    Drew Olson Guest

    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/.
     
    Drew Olson, Aug 8, 2007
    #11
  12. FireAphis

    FireAphis Guest

    On Aug 8, 5:35 pm, "Robert Dober" <> wrote:
    > On 8/8/07, <> 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 ;)
    >
    > 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


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

    Thanks again
    FireAphis
     
    FireAphis, Aug 9, 2007
    #12
  13. FireAphis

    FireAphis Guest

    On Aug 8, 4:43 pm, 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)


    Short and elegant!
     
    FireAphis, Aug 9, 2007
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. carl
    Replies:
    5
    Views:
    2,392
    James Kanze
    Nov 25, 2009
  2. Thaddeus L Olczyk

    Iterating over an area in pairs.

    Thaddeus L Olczyk, May 6, 2006, in forum: Ruby
    Replies:
    7
    Views:
    178
    Ross Bamford
    May 9, 2006
  3. Jerry Krinock
    Replies:
    7
    Views:
    328
    Eric Pozharski
    Sep 12, 2008
  4. Sven
    Replies:
    1
    Views:
    150
    Roy Smith
    Mar 7, 2013
  5. Sven
    Replies:
    3
    Views:
    164
    Steven D'Aprano
    Mar 8, 2013
Loading...

Share This Page