开发者

Python sorting multiple attributes

I have a dictionary like the following. Key value pairs or username:name

d = {"user2":"Tom Cruise", "user1": "Tom Cruise"}

My problem is that i need to sort these by the Name, but if multiple users contain the same name like above, i then need to sort those by their username. I looked up the sorted function but i dont really understand the cmp parameter and the lambd开发者_JAVA技巧a. If someone could explain those and help me with this that would be great! Thanks :)


cmp is obsolescent. lambda just makes a function.

sorted(d.iteritems(), key=operator.itemgetter(1, 0))


I'm just going to elaborate on Ignacio Vazquez-Abrams's answer. cmp is deprecated. Don't use it. Use the key attribute instead.

lambda makes a function. It's an expression and so can go places that a normal def statement can't but it's body is limited to a single expression.

my_func = lambda x: x + 1

This defines a function that takes a single argument, x and returns x + 1. lambda x, y=1: x + y defines a function that takes an x argument, an optional y argument with a default value of 1 and returns x + y. As you can see, it's really just like a def statement except that it's an expression and limited to a single expression for the body.

The purpose of the key attribute is that sorted will call it for each element of the sequence to be sorted and use the value that it returns for comparison.

list_ = ['a', 'b', 'c']
sorted(list_, key=lambda x: 1)

Just read the rest for a hypothetical example. I didn't look at problem closely enough before writing this. It will still be educational though so I'll leave it up. We can't really say much more because

  1. You can't sort dicts. Do you have a list of dictss? We could sort that.
  2. You haven't shown a username key.

I'll assume that it's something like

users = [{'name': 'Tom Cruise', 'username': user234234234, 'reputation': 1},
         {'name': 'Aaron Sterling', 'username': 'aaronasterling', 'reputation': 11725}]

If you wanted to confirm that I'm more awesome than Tom Cruise, you could do:

sorted(users, key=lambda x: x['reputation'])

This just passes a function that returns the 'reputation' value for each dictionary in the list. But lambdas can be slower. Most of the time operator.itemgetter is what you want.

operator.itemgetter takes a series of keys and returns a function that takes an object and returns a tuple of the value of its argument.

so f = operator.itemgetter('name', 'username') will return essentially the same function as lambda d: (d['name'], d['username']) The difference is that it should, in principle run much faster and you don't have to look at ugly lambda expressions.

So to sort a list of dicts by name and then username, just do

sorted(list_of_dicts, operator.itemgetter('name', 'username'))

which is exactly what Ignacio Vazquez-Abrams suggested.


You should know that dict can't be sorted. But python 2.7 & 3.1 have this class collections.OrderedDict.

So,

>>> from collections import OrderedDict
>>> d=OrderedDict({'D':'X','B':'Z','C':'X','A':'Y'})
>>> d
OrderedDict([('A', 'Y'), ('C', 'X'), ('B', 'Z'), ('D', 'X')])
>>> OrderedDict(sorted((d.items()), key=lambda t:(t[1],t[0])))
OrderedDict([('C', 'X'), ('D', 'X'), ('A', 'Y'), ('B', 'Z')])
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜