[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Is iterating in lock-step possible?

Roshan James

3/10/2005 12:53:00 PM

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



9 Answers

Brian Schröder

3/10/2005 1:02:00 PM

0

On Thu, 10 Mar 2005 21:52:43 +0900, Roshan James <roshanj@microsoft.com> wrote:
> 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

--
Brian Schröder
http://ruby.brian-sch...



ts

3/10/2005 1:06:00 PM

0

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


Brian Schröder

3/10/2005 2:28:00 PM

0

On Thu, 10 Mar 2005 22:06:10 +0900, ts <decoux@moulon.inra.fr> wrote:
> >>>>> "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

--
Brian Schröder
http://ruby.brian-sch...



Tom Willis

3/10/2005 2:56:00 PM

0

On Thu, 10 Mar 2005 23:28:24 +0900, Brian Schröder <ruby.brian@gmail.com> wrote:
> On Thu, 10 Mar 2005 22:06:10 +0900, ts <decoux@moulon.inra.fr> wrote:
> > >>>>> "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
>
> --
> Brian Schröder
> http://ruby.brian-sch...
>
>

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

--
Thomas G. Willis
http://paperbac...



dblack

3/10/2005 3:58:00 PM

0

Jason Sweat

3/10/2005 4:13:00 PM

0

On Thu, 10 Mar 2005 21:52:43 +0900, Roshan James <roshanj@microsoft.com> wrote:
> 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]


--
Regards,
Jason
http://blog.casey...


WoNáDo

3/11/2005 9:29:00 AM

0

--
Wolfgang Nádasi-Donner
wonado@donnerweb.de
"Roshan James" <roshanj@microsoft.com> schrieb im Newsbeitrag
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.

>>>> code >>>>>
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"}
>>>>> Result >>>>>
ai=1, bi=7
ai=2, bi=8
ai=3, bi=9
ai=4, bi=nil
ai=5, bi=nil
ai=6, bi=nil
>>>>> End Of Example >>>>>

Good luck.


WoNáDo

3/11/2005 9:57:00 AM

0

--
Wolfgang Nádasi-Donner
wonado@donnerweb.de
"Wolfgang Nádasi-Donner" <wonado@donnerweb.de> schrieb im Newsbeitrag
news:39d6okF61jtpsU1@uni-berlin.de...
> --
> Wolfgang Nádasi-Donner
> wonado@donnerweb.de
> "Roshan James" <roshanj@microsoft.com> schrieb im Newsbeitrag
>
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.
>
> >>>> code >>>>>
> 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"}
> >>>>> Result >>>>>
> ai=1, bi=7
> ai=2, bi=8
> ai=3, bi=9
> ai=4, bi=nil
> ai=5, bi=nil
> ai=6, bi=nil
> >>>>> End Of Example >>>>>
>
> 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.


Robert Klemme

3/11/2005 11:02:00 AM

0


"Wolfgang Nádasi-Donner" <wonado@donnerweb.de> schrieb im Newsbeitrag
news:39d8caF608mgiU1@uni-berlin.de...

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

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