Using s.sort([cmp[, key[, reverse]]]) to sort a list of objects based on a attribute

Discussion in 'Python' started by cjt22@bath.ac.uk, Sep 7, 2007.

  1. Guest

    Hi there

    I am fairly new to Python and have not really used regular expressions
    before (I think this might be needed for my query) and wondered if you
    could help

    I have a step class and store in a list step instances
    A step instance contains variables: name, startTime etc and startTime
    is stored as a string %H:%M:%S

    What I would like to do is to be able to sort this list of objects
    based on the startTime object so that the first item in the list is
    the object with the earliest Start time and last item is the object
    with the last Start time.

    I belive my key has to be = strpTime(step.sTime, "%H:%M:%S")
    But don't know how to create the comparison funciton.

    Any help on how I can perform this whole operation would be much
    appreciated.

    Thanks
    Chris
     
    , Sep 7, 2007
    #1
    1. Advertising

  2. Tim Golden Guest

    Re: Using s.sort([cmp[, key[, reverse]]]) to sort a list of objectsbased on a attribute

    wrote:
    > Hi there
    >
    > I am fairly new to Python and have not really used regular expressions
    > before (I think this might be needed for my query) and wondered if you
    > could help
    >
    > I have a step class and store in a list step instances
    > A step instance contains variables: name, startTime etc and startTime
    > is stored as a string %H:%M:%S
    >
    > What I would like to do is to be able to sort this list of objects
    > based on the startTime object so that the first item in the list is
    > the object with the earliest Start time and last item is the object
    > with the last Start time.
    >
    > I belive my key has to be = strpTime(step.sTime, "%H:%M:%S")
    > But don't know how to create the comparison funciton.


    You're going to get a *lot* of answers on this one!

    To start the ball rolling...

    <code>
    import random

    class Step:

    def __init__ (self, name, startTime):
    self.name = name
    self.startTime = startTime

    def __cmp__ (self, other):
    return cmp (self.startTime, other.startTime)

    def __str__ (self):
    return str (self.startTime)
    __repr__ = __str__

    steps = [Step (h, "%02d:00:00" % h) for h in range (10)]
    random.shuffle (steps)
    print "Shuffled:", steps

    steps.sort ()
    print "Sorted:", steps
    </code>

    In this case, I've given the class a ordering-semantic based
    on its startTime attribute. Obviously, this only makes sense
    if you *always* want your class to sort this way, rather than
    in this one instance.

    To do it on a per-sort basis, you *could* create simple per-sort
    equivalent:

    <code fragment>

    def compare_by_startTime (one, other):
    return cmp (one.startTime, other.startTime)

    steps.sort (cmp=compare_by_startTime)

    </code>

    or, in the case you're asking about, you could use the
    operator module's attrgetter function to do what you want:

    <code fragment>
    import operator

    steps.sort (key=operator.attrgetter ("startTime"))

    </code>

    TJG
     
    Tim Golden, Sep 7, 2007
    #2
    1. Advertising

  3. writes:

    > Hi there
    >
    > I am fairly new to Python and have not really used regular expressions
    > before (I think this might be needed for my query) and wondered if you
    > could help
    >
    > I have a step class and store in a list step instances
    > A step instance contains variables: name, startTime etc and startTime
    > is stored as a string %H:%M:%S
    >
    > What I would like to do is to be able to sort this list of objects
    > based on the startTime object so that the first item in the list is
    > the object with the earliest Start time and last item is the object
    > with the last Start time.
    >
    > I belive my key has to be = strpTime(step.sTime, "%H:%M:%S")
    > But don't know how to create the comparison funciton.
    >
    > Any help on how I can perform this whole operation would be much
    > appreciated.


    Code:

    class Step(object):
    def __init__(self, time):
    self.time = time
    def __repr__(self):
    return "<Step time=%s>" % self.time

    steps = [Step("03:23:23"), Step("12:59:12"), Step("02:32:17")]
    print steps

    steps.sort(key = lambda s: s.time)
    print steps

    Output:

    [<Step time=03:23:23>, <Step time=12:59:12>, <Step time=02:32:17>]
    [<Step time=02:32:17>, <Step time=03:23:23>, <Step time=12:59:12>]

    If the default sort order of a Step is always it's time then you can
    also define a __cmp__ method like this:

    class Step(object):
    def __cmp__(self, other):
    return cmp(self.time, other.time)

    And simply do a steps.sort()

    S.
     
    Stefan Arentz, Sep 7, 2007
    #3
  4. Re: Using s.sort([cmp[, key[, reverse]]]) to sort a list of objectsbased on a attribute

    On Fri, 07 Sep 2007 06:57:35 -0700, cjt22 wrote:

    > I have a step class and store in a list step instances
    > A step instance contains variables: name, startTime etc and startTime
    > is stored as a string %H:%M:%S
    >
    > What I would like to do is to be able to sort this list of objects
    > based on the startTime object so that the first item in the list is
    > the object with the earliest Start time and last item is the object
    > with the last Start time.
    >
    > I belive my key has to be = strpTime(step.sTime, "%H:%M:%S")
    > But don't know how to create the comparison funciton.
    >
    > Any help on how I can perform this whole operation would be much
    > appreciated.


    This should be enough::

    steps.sort(key=lambda s: s.startTime)

    If you sort strings of the form 'hh:mm:ss' the represented times are
    sorted chronological. No need to convert them to a number first.

    If the "natural" sort criterion for `Step` objects is the start time you
    might override `__cmp__()` of `Step`\s instead::

    def __cmp__(self, other):
    return cmp(self.startTime, other.startTime)

    Now you can just sort the list with ``steps.sort()``.

    Ciao,
    Marc 'BlackJack' Rintsch
     
    Marc 'BlackJack' Rintsch, Sep 7, 2007
    #4
  5. Miki Guest

    > steps.sort(key = lambda s: s.time)
    This is why attrgetter in the operator module was invented.
    from operator import attrgetter
    ....
    steps.sort(key=attrgettr("time"))

    HTH,
    --
    Miki <>
    http://pythonwise.blogspot.com
     
    Miki, Sep 9, 2007
    #5
  6. Miki <> writes:

    > > steps.sort(key = lambda s: s.time)

    > This is why attrgetter in the operator module was invented.
    > from operator import attrgetter
    > ...
    > steps.sort(key=attrgettr("time"))


    Personally I prefer the anonymous function over attrgettr :)

    S.
     
    Stefan Arentz, Sep 9, 2007
    #6
  7. Stefan Arentz <> wrote:

    > Miki <> writes:
    >
    > > > steps.sort(key = lambda s: s.time)

    > > This is why attrgetter in the operator module was invented.
    > > from operator import attrgetter
    > > ...
    > > steps.sort(key=attrgettr("time"))

    >
    > Personally I prefer the anonymous function over attrgettr :)


    However, Python disagrees with you...:

    brain:~ alex$ python -mtimeit -s'from operator import attrgetter;
    L=map(complex,xrange(999))' 'sorted(L, key=lambda x:x.real)'
    1000 loops, best of 3: 567 usec per loop

    brain:~ alex$ python -mtimeit -s'from operator import attrgetter;
    L=map(complex,xrange(999))' 'sorted(L, key=attrgetter("real"))'
    1000 loops, best of 3: 367 usec per loop

    A speed-up of 35% is a pretty clear indicator of what _Python_ "prefers"
    in this situation:).


    Alex
     
    Alex Martelli, Sep 9, 2007
    #7
  8. (Alex Martelli) writes:

    > Stefan Arentz <> wrote:
    >
    > > Miki <> writes:
    > >
    > > > > steps.sort(key = lambda s: s.time)
    > > > This is why attrgetter in the operator module was invented.
    > > > from operator import attrgetter
    > > > ...
    > > > steps.sort(key=attrgettr("time"))

    > >
    > > Personally I prefer the anonymous function over attrgettr :)

    >
    > However, Python disagrees with you...:
    >
    > brain:~ alex$ python -mtimeit -s'from operator import attrgetter;
    > L=map(complex,xrange(999))' 'sorted(L, key=lambda x:x.real)'
    > 1000 loops, best of 3: 567 usec per loop
    >
    > brain:~ alex$ python -mtimeit -s'from operator import attrgetter;
    > L=map(complex,xrange(999))' 'sorted(L, key=attrgetter("real"))'
    > 1000 loops, best of 3: 367 usec per loop
    >
    > A speed-up of 35% is a pretty clear indicator of what _Python_ "prefers"
    > in this situation:).


    I could not care less :)

    S.
     
    Stefan Arentz, Sep 10, 2007
    #8
    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. Andrea Sansottera

    no cmp field defined in cmp ejb

    Andrea Sansottera, Jul 16, 2004, in forum: Java
    Replies:
    0
    Views:
    416
    Andrea Sansottera
    Jul 16, 2004
  2. kj
    Replies:
    45
    Views:
    1,269
    Raymond Hettinger
    Oct 7, 2009
  3. Joshua Muheim
    Replies:
    3
    Views:
    170
    Xavier Noria
    Aug 28, 2008
  4. gb345

    Q: sort's key and cmp parameters

    gb345, Oct 1, 2009, in forum: Perl Misc
    Replies:
    1
    Views:
    107
  5. Mark Lawrence

    sort(*, key=None, reverse=None)

    Mark Lawrence, Dec 21, 2013, in forum: Python
    Replies:
    0
    Views:
    264
    Mark Lawrence
    Dec 21, 2013
Loading...

Share This Page