Using methodcaller in a list sort - any examples anywhere?

T

tinnews

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.
 
T

Tim Chase

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
 
P

Peter Otten

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"))
 
T

tinnews

Peter Otten said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top