Is iterating in lock-step possible?

R

Roshan James

I have been wondering is there is a way to do this. Can I have two
itertors working in lock-step - ie, can I have both of them return a
value each into the same loop body ?

a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
a.each {|a1|
b.each {|b1|
# this nests the call to b inside a
}
}

Is there someway I can do something like -
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
(a.each, b.each) {|a1, b1|
#so that I get one value from a and one from b
}

I hope I have made the idea clear, the above syntax is only illustrative
of what I mean.

This is possible in python because the iterators are fundamentally
objects that require an explicit next() call and are not bound to the
the loop body/block by syntax as in ruby.

Thanks in advance,
Roshan
 
B

Brian Schröder

I have been wondering is there is a way to do this. Can I have two
itertors working in lock-step - ie, can I have both of them return a
value each into the same loop body ?

a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
a.each {|a1|
b.each {|b1|
# this nests the call to b inside a
}
}

Is there someway I can do something like -
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
(a.each, b.each) {|a1, b1|
#so that I get one value from a and one from b
}

I hope I have made the idea clear, the above syntax is only illustrative
of what I mean.

This is possible in python because the iterators are fundamentally
objects that require an explicit next() call and are not bound to the
the loop body/block by syntax as in ruby.

Thanks in advance,
Roshan

Hello Roshan,

you can use the Generator class, to wrap any iterator into a generator
(i.e. get a .next function)

Or in simple cases where the additional memory overhead is not
important, you can also use the zip funtion. I.e.

%w(eins zwei drei).zip([1,2,3]).each do | name, value |
puts "The value of #{name} is #{value}"
end

regards,

Brian
 
T

ts

"B" == =?ISO-8859-1?Q?Brian Schr=F6der?= <ISO-8859-1> writes:

B> Or in simple cases where the additional memory overhead is not
B> important, you can also use the zip funtion. I.e.

B> %w(eins zwei drei).zip([1,2,3]).each do | name, value |
B> puts "The value of #{name} is #{value}"
B> end

Why do you use #each ?

svg% ruby -e '%w(eins zwei drei).zip([1,2,3]) {|a, b| puts "#{a} #{b}" }'
eins 1
zwei 2
drei 3
svg%

no memory overhead


Guy Decoux
 
B

Brian Schröder

B> Or in simple cases where the additional memory overhead is not
B> important, you can also use the zip funtion. I.e.

B> %w(eins zwei drei).zip([1,2,3]).each do | name, value |
B> puts "The value of #{name} is #{value}"
B> end

Why do you use #each ?

svg% ruby -e '%w(eins zwei drei).zip([1,2,3]) {|a, b| puts "#{a} #{b}" }'
eins 1
zwei 2
drei 3
svg%

no memory overhead

Guy Decoux

Thank you, I thought that was something not yet in the standard lib.
Wasn't there a discussion about this on this list not so long ago?
Anyway, learned something more.

regards,

Brian
 
T

Tom Willis

"B" == =?ISO-8859-1?Q?Brian Schr=F6der?= <ISO-8859-1> writes:

B> Or in simple cases where the additional memory overhead is not
B> important, you can also use the zip funtion. I.e.

B> %w(eins zwei drei).zip([1,2,3]).each do | name, value |
B> puts "The value of #{name} is #{value}"
B> end

Why do you use #each ?

svg% ruby -e '%w(eins zwei drei).zip([1,2,3]) {|a, b| puts "#{a} #{b}" }'
eins 1
zwei 2
drei 3
svg%

no memory overhead

Guy Decoux

Thank you, I thought that was something not yet in the standard lib.
Wasn't there a discussion about this on this list not so long ago?
Anyway, learned something more.

regards,

Brian

I needed to do this the other day, but I was too embarassed to ask. :(
 
D

David A. Black

--927295978-1099658342-1110470283=:21715
Content-Type: MULTIPART/MIXED; BOUNDARY="927295978-1099658342-1110470283=:21715"

This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.

--927295978-1099658342-1110470283=:21715
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

Hi --

"B" =3D=3D =3D?ISO-8859-1?Q?Brian Schr=3DF6der?=3D <ISO-8859-1> wri=
tes:

B> Or in simple cases where the additional memory overhead is not
B> important, you can also use the zip funtion. I.e.

B> %w(eins zwei drei).zip([1,2,3]).each do | name, value |
B> puts "The value of #{name} is #{value}"
B> end

Why do you use #each ?

svg% ruby -e '%w(eins zwei drei).zip([1,2,3]) {|a, b| puts "#{a} #{b}" }= '
eins 1
zwei 2
drei 3
svg%

no memory overhead

Guy Decoux

Thank you, I thought that was something not yet in the standard lib.
Wasn't there a discussion about this on this list not so long ago?

I think you might be thinking of discussion of the return value for
#zip when a block is used -- that is, whether it should return the
zipped array (as it does when there's no block) instead of nil.


David

--=20
David A. Black
(e-mail address removed)
--927295978-1099658342-1110470283=:21715--
--927295978-1099658342-1110470283=:21715--
 
J

Jason Sweat

Is there someway I can do something like -
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
(a.each, b.each) {|a1, b1|
#so that I get one value from a and one from b
}

Warning: total Ruby newby naive approach:
a = (1..4).to_a => [1, 2, 3, 4]
b = (5..8).to_a => [5, 6, 7, 8]
a.each_with_index {|av, ai| p [av, b[ai]]}
[1, 5]
[2, 6]
[3, 7]
[4, 8]
 
W

Wolfgang Nádasi-Donner

--
Wolfgang Nádasi-Donner
(e-mail address removed)
icrosoft.com...
I have been wondering is there is a way to do this. Can I have two
itertors working in lock-step - ie, can I have both of them return a
value each into the same loop body ?

a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
a.each {|a1|
b.each {|b1|
# this nests the call to b inside a
}
}

Is there someway I can do something like -
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
(a.each, b.each) {|a1, b1|
#so that I get one value from a and one from b
}

I hope I have made the idea clear, the above syntax is only illustrative
of what I mean.

This is possible in python because the iterators are fundamentally
objects that require an explicit next() call and are not bound to the
the loop body/block by syntax as in ruby.

Thanks in advance,
Roshan

the following works. It is oriented on the length of the first array. If the
second one is longer the rest of the values are ignored, if it is shorter,
"nil" will be returned.
class Array
def combeach(anarr)
self.each_index{|ind|
yield self[ind], anarr[ind]
}
end
end

a=[1,2,3,4,5,6]
b=[7,8,9]

a.combeach(b){|ai,bi| print "ai=#{ai.inspect}, bi=#{bi.inspect}\n"}ai=1, bi=7
ai=2, bi=8
ai=3, bi=9
ai=4, bi=nil
ai=5, bi=nil
ai=6, bi=nil
Good luck.
 
W

Wolfgang Nádasi-Donner

--
Wolfgang Nádasi-Donner
(e-mail address removed)
Wolfgang Nádasi-Donner said:
--
Wolfgang Nádasi-Donner
(e-mail address removed)
news:E8AA887D9A078F45B870125A37ED234701BC9564@APS-MSG-02.southpacific.corp.m
icrosoft.com...
I have been wondering is there is a way to do this. Can I have two
itertors working in lock-step - ie, can I have both of them return a
value each into the same loop body ?

a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
a.each {|a1|
b.each {|b1|
# this nests the call to b inside a
}
}

Is there someway I can do something like -
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
(a.each, b.each) {|a1, b1|
#so that I get one value from a and one from b
}

I hope I have made the idea clear, the above syntax is only illustrative
of what I mean.

This is possible in python because the iterators are fundamentally
objects that require an explicit next() call and are not bound to the
the loop body/block by syntax as in ruby.

Thanks in advance,
Roshan

the following works. It is oriented on the length of the first array. If the
second one is longer the rest of the values are ignored, if it is shorter,
"nil" will be returned.
class Array
def combeach(anarr)
self.each_index{|ind|
yield self[ind], anarr[ind]
}
end
end

a=[1,2,3,4,5,6]
b=[7,8,9]

a.combeach(b){|ai,bi| print "ai=#{ai.inspect}, bi=#{bi.inspect}\n"}ai=1, bi=7
ai=2, bi=8
ai=3, bi=9
ai=4, bi=nil
ai=5, bi=nil
ai=6, bi=nil
Good luck.
As I've seen in the last message you are directly looking for the "external
iterators", as implemented in C#.

Why? - It is somehow the "assembler-way" for iterators. The difference is
that you must put your algorthmic selection inside a method an then call the
block using "yield". This doesn't even make problems if you read a data
stream which length is not specified when starting the action.
 
R

Robert Klemme


The code works only for Array or other Enumerables that can be indexed by
an integer value. That does not cover the general case Roshan is after.
As I've seen in the last message you are directly looking for the "external
iterators", as implemented in C#.

Why? - It is somehow the "assembler-way" for iterators. The difference is
that you must put your algorthmic selection inside a method an then call the
block using "yield". This doesn't even make problems if you read a data
stream which length is not specified when starting the action.

If you look at the thread you'll see that Roshan does not want to use
Arrays; and he wants to iterate two Enumerables in lock step, i.e.,
iterate them in parallel, without paying the extra overhead of conversion
to Array beforehand - which is especially reasonable for Enumerables that
yield an infinite number of values.

Regards

robert
 

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

Forum statistics

Threads
474,169
Messages
2,570,919
Members
47,459
Latest member
Vida00R129

Latest Threads

Top