Grouping/Sorting an Array of objects

Discussion in 'Ruby' started by Howard Roberts, Jul 21, 2008.

  1. Suppose I have an array of two different kinds of objects, each with
    different attributes, but both having a date attribute. I'd like to be
    able to loop through the array in such a manner as to be able print a
    result similar to the following:


    07/19/08
    Foo-1 - Name
    attr 1
    attr 2
    [..]

    Foo-2 - Name
    attr 1
    attr 2
    [..]

    Bar - Name
    attr 1
    attr 2
    [..]
    07/20/08
    Foo-1 - Name
    attr 1
    attr 2
    [..]

    Bar - Name
    attr 1
    attr 2
    [..]
    etc.

    showing all of the Foo's first, then the Bar's, for each date.
    If I only have Foo's, I can easily do:

    @data.sort{|x,y| Time.parse(x.date) <=> Time.parse(y.date)}).each do
    |foo|
    puts Foo.date # Still shows date on each loop, but okay
    puts Foo.name
    [..]
    end

    To get things in date order, but when I consider mixing a second object
    into the array, that confounds matters for me. I suspect group_by{|item|
    item.class} may be part of the solution, but I'm not sure how?

    Any pointers would be most appreciated.

    Thanks,
    Howard
    --
    Posted via http://www.ruby-forum.com/.
    Howard Roberts, Jul 21, 2008
    #1
    1. Advertising

  2. RnJvbTogSG93YXJkIFJvYmVydHMgW21haWx0bzpob3dhcmRyb2JlcnRzQGNvbWNhc3QubmV0XSAN
    CiMuLi4NCiMgQGRhdGEuc29ydHt8eCx5fCBUaW1lLnBhcnNlKHguZGF0ZSkgPD0+IFRpbWUucGFy
    c2UoeS5kYXRlKX0pLmVhY2ggZG8NCiMgfGZvb3wNCiMgICBwdXRzIEZvby5kYXRlICMgU3RpbGwg
    c2hvd3MgZGF0ZSBvbiBlYWNoIGxvb3AsIGJ1dCBva2F5DQojICAgcHV0cyBGb28ubmFtZQ0KIyAg
    IFsuLl0NCiMgZW5kDQoNCnRyeSwNCg0KICBAZGF0YS5zb3J0X2J5e3xyZWN8IFtyZWMuZGF0ZSwg
    cmVjLmNsYXNzLCByZWMubmFtZV19DQoNCm9yIHNvbWV0aGluZyBsaWtlIHRoYXQuDQoNCml0IHdv
    dWxkIGJlIG5pY2UgaWYgeW91IGNhbiBwb3N0IHNvbWUgc2FtcGxlIGRhdGEgc28gd2UgY2FuIHRl
    c3QgaXQgaW1tZWRpYXRlbHkuIGknbSBhIHNsb3cgdHlwaXN0IDspDQoNCg0KIyBUbyBnZXQgdGhp
    bmdzIGluIGRhdGUgb3JkZXIsIGJ1dCB3aGVuIEkgY29uc2lkZXIgbWl4aW5nIGEgDQojIHNlY29u
    ZCBvYmplY3QgaW50byB0aGUgYXJyYXksIHRoYXQgY29uZm91bmRzIG1hdHRlcnMgZm9yIG1lLiAN
    CiMgSSBzdXNwZWN0IGdyb3VwX2J5e3xpdGVtfCBpdGVtLmNsYXNzfSBtYXkgYmUgcGFydCBvZiB0
    aGUgc29sdXRpb24sIA0KIyBidXQgSSdtIG5vdCBzdXJlIGhvdz8NCg0KdGhhdCBpcyBwb3NzaWJs
    ZSB0b28sIGJ1dCBsZXQgdXMgdGFrZSBpdCBvbmUgYXQgYSB0aW1lIDspDQoNCmtpbmQgcmVnYXJk
    cyAtYm90cA0K
    Peña, Botp, Jul 21, 2008
    #2
    1. Advertising

  3. Peña, Botp wrote:

    > try,
    >
    > @data.sort_by{|rec| [rec.date, rec.class, rec.name]}
    >
    > or something like that.


    Something like that is probably what I need, because the app doesn't
    like that line for me.
    > it would be nice if you can post some sample data so we can test it
    > immediately. i'm a slow typist ;)

    some sample data and pseudo code is here:
    http://ruby.pastebin.com/m24b5e03

    The output I'm trying to achieve would look like the following, listing
    first the date, then the information all of the first objects , and then
    all of the second objects for that date:

    7/18/08

    9:00 AM - Orientation
    Location: Conference Room
    Welcome, review agenda, and brief Q&A

    7:30 AM - First Event
    The Smiths invite you for a casual breakfast at Grumpy's

    7/19/08
    8:00 AM - Workshop I
    Location: Room 106
    Boring, all day presentation by Dr. Jones


    7/20/08
    6:00 PM - Second Event
    The Jones invite you for a Sociable Dinner at La Nepolara's

    7/21/08
    8:00 AM - Workshop II
    Location: Room 108
    Yet another boring, all day presentation by Dr. Jones

    2:30 PM - Wrap-Up
    Location: Room 108
    Summary, Q&A, and lots of free goodies

    7:30 AM - Third Event
    The Smiths invite you for a casual Breakfast at Mel's

    1:00 PM - Fourth Event
    Dr. Jones and Staff invite you for a Business Lunch at The Krusty Krab


    > kind regards -botp

    Thank you kindly for replying and a for any suggestions you might offer.

    Howard

    --
    Posted via http://www.ruby-forum.com/.
    Howard Roberts, Jul 21, 2008
    #3
  4. Peña, Botp wrote:
    > prev_date=nil
    > @data.sort_by do |item|
    > t,ampm = item.time.split
    > hr,min = t.split ":"
    > hr = "0"+hr if hr.size==1
    > timenew = ampm+hr+min
    > [item.date, timenew, item.class.to_s]
    > end.each do |item|


    Brilliant!

    > There's some clobbering of time in there since i arranged by time too :)

    I can adapt my app for that.

    > Is that ok?
    > Kind regards -botp


    -botp,
    This is superb! I was reluctant to ask for help on this at all because
    it sounded so much like I was asking "write my code for me." But I would
    have never gotten that, because I did not know you could use sort_by in
    such a way-- passing an array as the last line of the block. It is
    exactly what I needed and I am most grateful-- for the clearer
    understanding (and the code :)

    Thank You,
    Howard



    --
    Posted via http://www.ruby-forum.com/.
    Howard Roberts, Jul 22, 2008
    #4
  5. Hi --

    On Mon, 21 Jul 2008, Howard Roberts wrote:

    > Suppose I have an array of two different kinds of objects, each with
    > different attributes, but both having a date attribute. I'd like to be
    > able to loop through the array in such a manner as to be able print a
    > result similar to the following:
    >
    >
    > 07/19/08
    > Foo-1 - Name
    > attr 1
    > attr 2
    > [..]
    >
    > Foo-2 - Name
    > attr 1
    > attr 2
    > [..]
    >
    > Bar - Name
    > attr 1
    > attr 2
    > [..]
    > 07/20/08
    > Foo-1 - Name
    > attr 1
    > attr 2
    > [..]
    >
    > Bar - Name
    > attr 1
    > attr 2
    > [..]
    > etc.
    >
    > showing all of the Foo's first, then the Bar's, for each date.
    > If I only have Foo's, I can easily do:
    >
    > @data.sort{|x,y| Time.parse(x.date) <=> Time.parse(y.date)}).each do
    > |foo|
    > puts Foo.date # Still shows date on each loop, but okay
    > puts Foo.name
    > [..]
    > end
    >
    > To get things in date order, but when I consider mixing a second object
    > into the array, that confounds matters for me. I suspect group_by{|item|
    > item.class} may be part of the solution, but I'm not sure how?
    >
    > Any pointers would be most appreciated.


    Here's a stab at it: http://pastie.org/238521. I've put the sorting
    intelligence in the objects, and also given them to_s methods so you
    don't have to do all that formatting in the calling code (though you
    can, of course, if you want a different output).

    The last ten lines still seem a bit wordy to me but so be it; I have
    to go get ready for work :)


    David

    --
    Rails training from David A. Black and Ruby Power and Light:
    Intro to Ruby on Rails July 21-24 Edison, NJ
    * Advancing With Rails August 18-21 Edison, NJ
    * Co-taught by D.A. Black and Erik Kastner
    See http://www.rubypal.com for details and updates!
    David A. Black, Jul 22, 2008
    #5
  6. a.group_by do |o|
    o.date
    end.sort.each do |date, list|
    p date

    list.group_by do |o|
    o.class
    end.sort_by do |klass, _|
    [Foo, Bar].index(klass) # kind_of?
    end.each do |klass, list|
    list.each do |o|
    p o
    end
    end
    end

    gegroet,
    Erik V. - http://www.erikveen.dds.nl/
    Erik Veenstra, Jul 22, 2008
    #6
    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. Christian Ludwig

    XSLT: sorting and grouping

    Christian Ludwig, Nov 24, 2003, in forum: XML
    Replies:
    2
    Views:
    598
    Christian Ludwig
    Nov 26, 2003
  2. Jack Wayne
    Replies:
    0
    Views:
    453
    Jack Wayne
    Jan 24, 2005
  3. markspace
    Replies:
    1
    Views:
    379
    markspace
    Jun 25, 2009
  4. Roedy Green
    Replies:
    1
    Views:
    427
    Roedy Green
    Jun 25, 2009
Loading...

Share This Page