Running multiple closures per iteration

Discussion in 'Ruby' started by Joshua Chia, Aug 3, 2007.

  1. Joshua Chia

    Joshua Chia Guest

    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.
    --
    Posted via http://www.ruby-forum.com/.
    Joshua Chia, Aug 3, 2007
    #1
    1. Advertising

  2. Joshua Chia 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.

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Aug 3, 2007
    #2
    1. Advertising

  3. Joshua Chia

    Joshua Chia Guest

    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.
    --
    Posted via http://www.ruby-forum.com/.
    Joshua Chia, Aug 3, 2007
    #3
  4. Joshua Chia

    Tim Pease Guest

    On 8/3/07, Joshua Chia <> 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
    Tim Pease, Aug 3, 2007
    #4
  5. On Aug 3, 7:38 pm, Joshua Chia <> 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 }

    --
    S.
    Stefano Cobianchi, Aug 3, 2007
    #5
  6. Joshua Chia

    Guest

    Hi --

    On Sat, 4 Aug 2007, Stefano Cobianchi wrote:

    > On Aug 3, 7:38 pm, Joshua Chia <> 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 }

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

    :)


    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 3, 2007
    #6
  7. Tim Pease schrieb:
    > On 8/3/07, Joshua Chia <> 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


    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
    Simon Kröger, Aug 4, 2007
    #7
    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. =?Utf-8?B?S01aX3N0YXRl?=

    Quick one - Is SESSION per browser instance or per IP Address?

    =?Utf-8?B?S01aX3N0YXRl?=, Apr 4, 2006, in forum: ASP .Net
    Replies:
    7
    Views:
    5,864
    gerry
    Apr 10, 2006
  2. Razvan
    Replies:
    1
    Views:
    405
    tony vee
    Sep 10, 2004
  3. Replies:
    5
    Views:
    2,522
  4. Replies:
    0
    Views:
    340
  5. Rudi
    Replies:
    5
    Views:
    4,974
Loading...

Share This Page