Iterating list in pairs

F

FireAphis

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
 
D

dblack

A

Alex Young

FireAphis said:
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 :)
 
J

Jano Svitok

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) {|...| ...}
 
A

Alex Young

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

Jano Svitok

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.
 
D

dblack

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

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)
 
R

Robert Dober

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

but the version with first is not released yet :(

Robert
 
D

dblack

Hi --

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)
 
R

Robert Dober

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
 
D

Drew Olson

FireAphis said:
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]]
 
F

FireAphis

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

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

Thanks again
FireAphis
 
F

FireAphis

Hi --

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!
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top