Running multiple closures per iteration

Is there a way to run more than one closure per iteration through a
collection? For example, if I want to do the following two things, can
I combine them so that I only end up with one pass over the collection,
without doing a manual for loop?

o = a.select {|x| x >= 0}
p = a.inject(0) {|s, x| s += x}

Such a combination is useful when iterating through a collection is
expensive, e.g. on a large file on a slow disk.

Joshua C. wrote:

Is there a way to run more than one closure per iteration through a
collection? For example, if I want to do the following two things, can
I combine them so that I only end up with one pass over the collection,
without doing a manual for loop?

o = a.select {|x| x >= 0}
p = a.inject(0) {|s, x| s += x}

Such a combination is useful when iterating through a collection is
expensive, e.g. on a large file on a slow disk.

Did you mean

o = a.select {|x| x >= 0}
p = o.inject(0) {|s, x| s += x}
^^^
?

Then you can do this:

a = [1,-1,2,-2,3,-3]
sp = a.inject(0) {|s, x| x >= 0 ? s + x : s}
p sp # ==> 6

(note that += is not needed, + is good enough)

But there is no way in general to combine two iterations.

Joel VanderWerf wrote:

Did you mean

o = a.select {|x| x >= 0}
p = o.inject(0) {|s, x| s += x}
^^^
?

No, I meant to compute two different things from a.

On 8/3/07, Joshua C. [email protected] wrote:

Joel VanderWerf wrote:

Did you mean

o = a.select {|x| x >= 0}
p = o.inject(0) {|s, x| s += x}
^^^
?

No, I meant to compute two different things from a.

Well, it’s not pretty, but here’s my best shot at it

o, p = a.inject( [[], 0] ) do |ary,x|
ary[0] << x if x >= 0
ary[1] += x
ary
end

I don’t think Ruby natively supports such a creature, though. Please
correct me if I’m wrong.

Blessings,
TwP

Hi –

On Sat, 4 Aug 2007, Stefano C. wrote:

a.inject(0) {|s, x| s + x}
=> 6

Such a combination is useful when iterating through a collection is
expensive, e.g. on a large file on a slow disk.

o = 0; p = []
a.each { |x| o << x if x >= 0; p += x }
a.each { |x| p << x if x >= 0; o += x }

:slight_smile:

David

On Aug 3, 7:38 pm, Joshua C. [email protected] wrote:

Is there a way to run more than one closure per iteration through a
collection? For example, if I want to do the following two things, can
I combine them so that I only end up with one pass over the collection,
without doing a manual for loop?

o = a.select {|x| x >= 0}
p = a.inject(0) {|s, x| s += x}

btw, you don’t need the += operator here:
a.inject(0) {|s, x| s + x}
=> 6

Such a combination is useful when iterating through a collection is
expensive, e.g. on a large file on a slow disk.

o = 0; p = []
a.each { |x| o << x if x >= 0; p += x }

Tim P. schrieb:

Well, it’s not pretty, but here’s my best shot at it

o, p = a.inject( [[], 0] ) do |ary,x|
ary[0] << x if x >= 0
ary[1] += x
ary
end

you can beautify this to

o, p = a.inject( [[], 0] ) do |(l, s), x|
[x >= 0 ? l << x : l, s + x]
end

I don’t think Ruby natively supports such a creature, though. Please
correct me if I’m wrong.

Well, depends on what ‘natively’ realy means…

Blessings,
TwP

cheers

Simon