splitting Array - DRY

Discussion in 'Ruby' started by Josselin, Aug 19, 2007.

  1. Josselin

    Josselin Guest

    I am presently splitting an array on 4 successives periods of time , is
    there a DRYest way to do it, or that's the way to go ? thanks

    @ads_id_w1 = advertisings.map {|ad| ad.id if ((ad.valid_until -
    ad.created_at) / 86400.0 <= 7)}.compact

    @ads_id_w2 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    ad.created_at) / 86400.0 > 7) && ((ad.valid_until - ad.created_at) /
    86400.0 <= 14)) }.compact

    @ads_id_w3 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    ad.created_at) / 86400.0 > 14) && ((ad.valid_until - ad.created_at) /
    86400.0 <= 21)) }.compact

    @ads_id_w4 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    ad.created_at) / 86400.0 > 21) && ((ad.valid_until - ad.created_at) /
    86400.0 <= 31)) }.compact
    Josselin, Aug 19, 2007
    #1
    1. Advertising

  2. Josselin wrote:
    > I am presently splitting an array on 4 successives periods of time , is
    > there a DRYest way to do it, or that's the way to go ? thanks
    >
    > @ads_id_w1 = advertisings.map {|ad| ad.id if ((ad.valid_until -
    > ad.created_at) / 86400.0 <= 7)}.compact
    >
    > @ads_id_w2 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    > ad.created_at) / 86400.0 > 7) && ((ad.valid_until - ad.created_at) /
    > 86400.0 <= 14)) }.compact
    >
    > @ads_id_w3 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    > ad.created_at) / 86400.0 > 14) && ((ad.valid_until - ad.created_at) /
    > 86400.0 <= 21)) }.compact
    >
    > @ads_id_w4 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    > ad.created_at) / 86400.0 > 21) && ((ad.valid_until - ad.created_at) /
    > 86400.0 <= 31)) }.compact


    class ClassOfAd
    def week # may want to name it differently
    return nil unless whateverdate.between?(acceptable_start,
    acceptable_end) # your call here
    ((ad.valid_until - ad.created_at).div(604800)) % 4
    end
    @ads_id = Array.new(4) { [] }
    advertisings.each {|ad| @ads_id[ad.week] = ad.id if ad.week }

    Depending on your needs that code can be condensed a bit more.

    Regards
    Stefan
    --
    Posted via http://www.ruby-forum.com/.
    Stefan Rusterholz, Aug 19, 2007
    #2
    1. Advertising

  3. Josselin

    Josselin Guest

    On 2007-08-19 09:58:46 +0200, Stefan Rusterholz <> said:

    > Josselin wrote:
    >> I am presently splitting an array on 4 successives periods of time , is
    >> there a DRYest way to do it, or that's the way to go ? thanks
    >>
    >> @ads_id_w1 = advertisings.map {|ad| ad.id if ((ad.valid_until -
    >> ad.created_at) / 86400.0 <= 7)}.compact
    >>
    >> @ads_id_w2 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    >> ad.created_at) / 86400.0 > 7) && ((ad.valid_until - ad.created_at) /
    >> 86400.0 <= 14)) }.compact
    >>
    >> @ads_id_w3 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    >> ad.created_at) / 86400.0 > 14) && ((ad.valid_until - ad.created_at) /
    >> 86400.0 <= 21)) }.compact
    >>
    >> @ads_id_w4 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    >> ad.created_at) / 86400.0 > 21) && ((ad.valid_until - ad.created_at) /
    >> 86400.0 <= 31)) }.compact

    >
    > class ClassOfAd
    > def week # may want to name it differently
    > return nil unless whateverdate.between?(acceptable_start,
    > acceptable_end) # your call here
    > ((ad.valid_until - ad.created_at).div(604800)) % 4
    > end
    > @ads_id = Array.new(4) { [] }
    > advertisings.each {|ad| @ads_id[ad.week] = ad.id if ad.week }
    >
    > Depending on your needs that code can be condensed a bit more.
    >
    > Regards
    > Stefan


    thanks Stefan, I realize that, too frequently, I am programming Ruby as
    C .. not using the OO potential
    what's one of the best book about "Programming Ruby, the way it should
    be..." ?
    I need to practise outside my app dev

    note : also found that the 'week' has been already written.. :
    (ad.valid_until - ad.created_at) >= 2.weeks
    Josselin, Aug 20, 2007
    #3
  4. 2007/8/20, Josselin <>:
    > On 2007-08-19 09:58:46 +0200, Stefan Rusterholz <> said:
    >
    > > Josselin wrote:
    > >> I am presently splitting an array on 4 successives periods of time , is
    > >> there a DRYest way to do it, or that's the way to go ? thanks
    > >>
    > >> @ads_id_w1 = advertisings.map {|ad| ad.id if ((ad.valid_until -
    > >> ad.created_at) / 86400.0 <= 7)}.compact
    > >>
    > >> @ads_id_w2 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    > >> ad.created_at) / 86400.0 > 7) && ((ad.valid_until - ad.created_at) /
    > >> 86400.0 <= 14)) }.compact
    > >>
    > >> @ads_id_w3 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    > >> ad.created_at) / 86400.0 > 14) && ((ad.valid_until - ad.created_at) /
    > >> 86400.0 <= 21)) }.compact
    > >>
    > >> @ads_id_w4 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    > >> ad.created_at) / 86400.0 > 21) && ((ad.valid_until - ad.created_at) /
    > >> 86400.0 <= 31)) }.compact

    > >
    > > class ClassOfAd
    > > def week # may want to name it differently
    > > return nil unless whateverdate.between?(acceptable_start,
    > > acceptable_end) # your call here
    > > ((ad.valid_until - ad.created_at).div(604800)) % 4
    > > end
    > > @ads_id = Array.new(4) { [] }
    > > advertisings.each {|ad| @ads_id[ad.week] = ad.id if ad.week }
    > >
    > > Depending on your needs that code can be condensed a bit more.
    > >
    > > Regards
    > > Stefan

    >
    > thanks Stefan, I realize that, too frequently, I am programming Ruby as
    > C .. not using the OO potential
    > what's one of the best book about "Programming Ruby, the way it should
    > be..." ?
    > I need to practise outside my app dev
    >
    > note : also found that the 'week' has been already written.. :
    > (ad.valid_until - ad.created_at) >= 2.weeks


    Basically you need a more generalized version of partition. Maybe
    something like this works:

    @ads_id = advertisings.inject(Hash.new {|h,k| h[k]=[]}) do |h,ad|
    h[(((ad.valid_until - ad.created_at) / 86400 - 1) / 7] << ad.id
    h
    end

    Note, I'm using interger arithmetic to reduce the number of result values.

    Kind regards

    robert
    Robert Klemme, Aug 20, 2007
    #4
  5. > what's one of the best book about "Programming Ruby, the way it should
    > be..." ?


    the Ruby Cookbook (ISBN: 0-596-52369-6) is really great, as it's
    almost entirely working examples with lots of commentary (I learn by
    doing/copying/changing), and has a curve that makes it great for
    learning and also for later reference. also many of the examples
    showcase various gems, which is very helpful for me. The table of
    contents makes it very easy for me to find exactly what I'm looking
    for. (Chapter 4: Arrays... 4.13: Extracting Portions of Arrays) highly
    recommended!

    being a beginner to programming in general, Beginning Ruby (ISBN:
    1590597664) covers a lot of great information, including a whole big
    chapter on documentation, (I wouldn't have thought of looking into
    RDoc otherwise!) error handling, debugging and testing... seeing as
    how unit testing seems like a big part of ruby, and how I just
    wouldn't have thought of looking into it, I find this very helpful as
    well. and that's where I am in that book, about halfway, chapter
    8/16+appendices, so it'll probably get somewhat advanced. knowing C
    already, I don't know if I could recommend it, but perhaps some
    foundation-up learning could be helpful. The early stuff shouldn't be
    TOO painful, as I'd bet that ruby and C differ pretty early on.
    Simon Schuster, Aug 20, 2007
    #5
  6. Josselin

    Josselin Guest

    On 2007-08-20 09:56:02 +0200, "Robert Klemme"
    <> said:

    > 2007/8/20, Josselin <>:
    >> On 2007-08-19 09:58:46 +0200, Stefan Rusterholz <> said:
    >>
    >>> Josselin wrote:
    >>>> I am presently splitting an array on 4 successives periods of time , is
    >>>> there a DRYest way to do it, or that's the way to go ? thanks
    >>>>
    >>>> @ads_id_w1 = advertisings.map {|ad| ad.id if ((ad.valid_until -
    >>>> ad.created_at) / 86400.0 <= 7)}.compact
    >>>>
    >>>> @ads_id_w2 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    >>>> ad.created_at) / 86400.0 > 7) && ((ad.valid_until - ad.created_at) /
    >>>> 86400.0 <= 14)) }.compact
    >>>>
    >>>> @ads_id_w3 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    >>>> ad.created_at) / 86400.0 > 14) && ((ad.valid_until - ad.created_at) /
    >>>> 86400.0 <= 21)) }.compact
    >>>>
    >>>> @ads_id_w4 = advertisings.map {|ad| ad.id if (((ad.valid_until -
    >>>> ad.created_at) / 86400.0 > 21) && ((ad.valid_until - ad.created_at) /
    >>>> 86400.0 <= 31)) }.compact
    >>>
    >>> class ClassOfAd
    >>> def week # may want to name it differently
    >>> return nil unless whateverdate.between?(acceptable_start,
    >>> acceptable_end) # your call here
    >>> ((ad.valid_until - ad.created_at).div(604800)) % 4
    >>> end
    >>> @ads_id = Array.new(4) { [] }
    >>> advertisings.each {|ad| @ads_id[ad.week] = ad.id if ad.week }
    >>>
    >>> Depending on your needs that code can be condensed a bit more.
    >>>
    >>> Regards
    >>> Stefan

    >>
    >> thanks Stefan, I realize that, too frequently, I am programming Ruby as
    >> C .. not using the OO potential
    >> what's one of the best book about "Programming Ruby, the way it should
    >> be..." ?
    >> I need to practise outside my app dev
    >>
    >> note : also found that the 'week' has been already written.. :
    >> (ad.valid_until - ad.created_at) >= 2.weeks

    >
    > Basically you need a more generalized version of partition. Maybe
    > something like this works:
    >
    > @ads_id = advertisings.inject(Hash.new {|h,k| h[k]=[]}) do |h,ad|
    > h[(((ad.valid_until - ad.created_at) / 86400 - 1) / 7] << ad.id
    > h
    > end
    >
    > Note, I'm using interger arithmetic to reduce the number of result values.
    >
    > Kind regards
    >
    > robert


    Thanks Robert... I'll put it in my Personal Ruby Cookbook, that's DRYissimo !
    Josselin, Aug 22, 2007
    #6
  7. Josselin

    Kaldrenon Guest

    On Aug 20, 3:58 am, "Simon Schuster" <> wrote:
    > > what's one of the best book about "Programming Ruby, the way it should
    > > be..." ?

    >
    > the Ruby Cookbook (ISBN: 0-596-52369-6) is really great, as it's
    > almost entirely working examples with lots of commentary (I learn by
    > doing/copying/changing), and has a curve that makes it great for
    > learning and also for later reference.


    I have this book too, and I haven't really delved into it, but I can
    tell it's definitely worth having. After all, it's an O'Reilly book.

    > being a beginner to programming in general, Beginning Ruby (ISBN:
    > 1590597664) covers a lot of great information, including a whole big
    > chapter on documentation, (I wouldn't have thought of looking into
    > RDoc otherwise!) error handling, debugging and testing... seeing as
    > how unit testing seems like a big part of ruby, and how I just
    > wouldn't have thought of looking into it, I find this very helpful as
    > well. and that's where I am in that book, about halfway, chapter
    > 8/16+appendices, so it'll probably get somewhat advanced. knowing C
    > already, I don't know if I could recommend it, but perhaps some
    > foundation-up learning could be helpful. The early stuff shouldn't be
    > TOO painful, as I'd bet that ruby and C differ pretty early on.


    The Pickaxe (the official title is "Programming Ruby - the Pragmatic
    Programmers' Guide, 2nd Ed.") is also an excellent resource - highly
    informative, well formated code examples, very readable. Might not get
    shelved under comedy, but still pretty entertaining, for a programming
    book.

    If you're LOOKING for comedy, _why's (Poignant) Guide to Ruby is where
    it's at. poignantguide.net 'Nuff said.

    GL, HF
    Kaldrenon, Aug 22, 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.

Share This Page