Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #17142 > unrolled thread

Using methodcaller in a list sort - any examples anywhere?

Started bytinnews@isbd.co.uk
First post2011-12-13 15:48 +0000
Last post2011-12-13 10:08 -0600
Articles 4 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  Using methodcaller in a list sort - any examples anywhere? tinnews@isbd.co.uk - 2011-12-13 15:48 +0000
    Re: Using methodcaller in a list sort - any examples anywhere? Peter Otten <__peter__@web.de> - 2011-12-13 17:13 +0100
      Re: Using methodcaller in a list sort - any examples anywhere? tinnews@isbd.co.uk - 2011-12-13 16:48 +0000
    Re: Using methodcaller in a list sort - any examples anywhere? Tim Chase <python.list@tim.thechases.com> - 2011-12-13 10:08 -0600

#17142 — Using methodcaller in a list sort - any examples anywhere?

Fromtinnews@isbd.co.uk
Date2011-12-13 15:48 +0000
SubjectUsing methodcaller in a list sort - any examples anywhere?
Message-ID<hm8kr8-uge.ln1@chris.zbmc.eu>
I want to sort a list of 'things' (they're fairly complex objects) by
the contents of one of the fields I can extract from the 'things'
using a Python function.

So I have a list L which is a list of objects of some sort.  I can
output the contents of a field in the list as follows:-

    for k in L:
        print k.get_property('family-name')

How can I sort the list first?  As I said it seems like a methodcaller
is the answer but I don't see how.  I want to sort the list of objects
not just produce a sorted list of names.

-- 
Chris Green

[toc] | [next] | [standalone]


#17145

FromPeter Otten <__peter__@web.de>
Date2011-12-13 17:13 +0100
Message-ID<mailman.3602.1323792823.27778.python-list@python.org>
In reply to#17142
tinnews@isbd.co.uk wrote:

> I want to sort a list of 'things' (they're fairly complex objects) by
> the contents of one of the fields I can extract from the 'things'
> using a Python function.
> 
> So I have a list L which is a list of objects of some sort.  I can
> output the contents of a field in the list as follows:-
> 
>     for k in L:
>         print k.get_property('family-name')
> 
> How can I sort the list first?  As I said it seems like a methodcaller
> is the answer but I don't see how.  I want to sort the list of objects
> not just produce a sorted list of names.

The most obvious way is to use a custom function

def get_family_name(obj):
    return obj.get_property("family-name")
L.sort(key=get_family_name)

However, since you already know about methodcaller

""" 
class methodcaller(builtins.object)
 |  methodcaller(name, ...) --> methodcaller object
 |
 |  Return a callable object that calls the given method on its operand.
 |  After, f = methodcaller('name'), the call f(r) returns r.name().
 |  After, g = methodcaller('name', 'date', foo=1), the call g(r) returns
 |  r.name('date', foo=1).
""""

L.sort(key=methodcaller("get_property", "family-name"))

[toc] | [prev] | [next] | [standalone]


#17152

Fromtinnews@isbd.co.uk
Date2011-12-13 16:48 +0000
Message-ID<j8ckr8-b84.ln1@chris.zbmc.eu>
In reply to#17145
Peter Otten <__peter__@web.de> wrote:
> tinnews@isbd.co.uk wrote:
> 
> > I want to sort a list of 'things' (they're fairly complex objects) by
> > the contents of one of the fields I can extract from the 'things'
> > using a Python function.
> > 
> > So I have a list L which is a list of objects of some sort.  I can
> > output the contents of a field in the list as follows:-
> > 
> >     for k in L:
> >         print k.get_property('family-name')
> > 
> > How can I sort the list first?  As I said it seems like a methodcaller
> > is the answer but I don't see how.  I want to sort the list of objects
> > not just produce a sorted list of names.
> 
> The most obvious way is to use a custom function
> 
> def get_family_name(obj):
>     return obj.get_property("family-name")
> L.sort(key=get_family_name)
> 
> However, since you already know about methodcaller
> 
> """ 
> class methodcaller(builtins.object)
>  |  methodcaller(name, ...) --> methodcaller object
>  |
>  |  Return a callable object that calls the given method on its operand.
>  |  After, f = methodcaller('name'), the call f(r) returns r.name().
>  |  After, g = methodcaller('name', 'date', foo=1), the call g(r) returns
>  |  r.name('date', foo=1).
> """"
> 
> L.sort(key=methodcaller("get_property", "family-name"))
> 
OK, thanks, just what I wanted.

-- 
Chris Green

[toc] | [prev] | [next] | [standalone]


#17155

FromTim Chase <python.list@tim.thechases.com>
Date2011-12-13 10:08 -0600
Message-ID<mailman.3607.1323796837.27778.python-list@python.org>
In reply to#17142
On 12/13/11 09:48, tinnews@isbd.co.uk wrote:
> I want to sort a list of 'things' (they're fairly complex objects) by
> the contents of one of the fields I can extract from the 'things'
> using a Python function.
>
> So I have a list L which is a list of objects of some sort.  I can
> output the contents of a field in the list as follows:-
>
>      for k in L:
>          print k.get_property('family-name')
>
> How can I sort the list first?  As I said it seems like a methodcaller
> is the answer but I don't see how.  I want to sort the list of objects
> not just produce a sorted list of names.

You want either sorted(..., key=...) to sort and return a copy 
(leaving the original unmodified) or .sort(key=...) to sort the 
list in-place:

   class MyObj(object):
     def __init__(self, fn): self.fn = fn
     def get_property(self, s): return "%s: %s" % (s, self.fn)
     def __str__(self): return self.fn
     __repr__ = __str__

   source = [
     MyObj("Doug"),
     MyObj("Carol"),
     MyObj("Bill"),
     MyObj("Adam"),
     ]

   print "Unsorted source before:"
   print repr(source)
   print "Using a lambda:"
   print repr(sorted(source,
     key=lambda mo: mo.get_property("family-name")))

   print "Using methodcaller:"
   from operator import methodcaller
   print repr(sorted(source,
     key=methodcaller("get_property", "family-name")))

   print "Source still unsorted after:"
   print repr(source)
   source.sort(key=lambda mo: mo.get_property("family-name"))
   print "Source now sorted:"
   print repr(source)

yields the following:

   Unsorted source before:
   [Doug, Carol, Bill, Adam]
   Using a lambda:
   [Adam, Bill, Carol, Doug]
   Using methodcaller:
   [Adam, Bill, Carol, Doug]
   Source still unsorted after:
   [Doug, Carol, Bill, Adam]
   Source now sorted:
   [Adam, Bill, Carol, Doug]

I'm partial to the lambda version over the methodcaller version 
unless there's a reason to dynamically get the method-name as a 
string.  But that's just a personal preference.

-tkc


[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web