2013-04-18 8 views
59

リストを最初に値でソートし、次に2番目の値でソートするとします。これを行う簡単な方法はありますか?ここで小さな例です:Python:辞書のリストをいくつかの値で並べ替えるには?

sorted(A, key = lambda user: user['name']) 

しかし、私は第二の値によって、このリストを並べ替えることができる方法:

A = [{'name':'john','age':45}, 
    {'name':'andi','age':23}, 
    {'name':'john','age':22}, 
    {'name':'paul','age':35}, 
    {'name':'john','age':21}] 

このコマンドは'name'ことで、このリストをソートするのですか?この例では'age'のようになります。

私は('age'によってソートその後、'name'による最初のソートと)このように並べ替えをしたい:

andi - 23 
john - 21 
john - 22 
john - 45 
paul - 35 

ありがとう!二つの属性の組によって

+5

サイドではありません:pythonのソートは安定していると保証されています。したがって、あなたは単に 'age'で'ソート 'し、' name'で簡単にソートすることができます。 (キーは逆順になっていますので、最初に2番目のキーで並べ替え、次に2番目のキーでソートします)。 – Bakuriu

答えて

85
>>> A = [{'name':'john','age':45}, 
    {'name':'andi','age':23}, 
    {'name':'john','age':22}, 
    {'name':'paul','age':35}, 
    {'name':'john','age':21}] 
>>> sorted(A, key = lambda user: (user['name'], user['age'])) 
[{'age': 23, 'name': 'andi'}, {'age': 21, 'name': 'john'}, {'age': 22, 'name': 'john'}, {'age': 45, 'name': 'john'}, {'age': 35, 'name': 'paul'}] 

このソートは、以下が同等とはるかに高速/クリーナーです:

>>> from operator import itemgetter 
>>> sorted(A, key=itemgetter('name', 'age')) 
[{'age': 23, 'name': 'andi'}, {'age': 21, 'name': 'john'}, {'age': 22, 'name': 'john'}, {'age': 45, 'name': 'john'}, {'age': 35, 'name': 'paul'}] 

のコメント:@Bakuriu

私はそこにある賭けます両者の大きな違いはありませんが、itemgetterは、キーを抽出して単一のオペコード(CALL_FUNCTION)の間にtupleを作成し、lambdaは関数を呼び出す必要があり、さまざまな定数(他のバイトコード)をロードし、最後に添字(BINARY_SUBSCR)を呼び出してtupleを構築し、それを返します...これはインタープリタのためにはるかに多くの作業です。

要約すると:itemgetterCレベルで完全に実行を続けるので、できるだけ速くます。

+3

私は説明に興味があるでしょう*なぜ* itemgetterラムダ式よりもはるかに速くなります。それは同じルックアップに沸騰しないのですか? – catchmeifyoutry

+4

@catchmeifyoutry私は2つの間に*大きな差はないと思うが、 'itemgetter'はキーを抽出して単一のオペコード(' CALL_FUNCTION')の間にタプルを作るので少しのオーバーヘッドを避け、 (BINARY_SUBSCR')を呼び出し、タプルを構築して返してください...それは通訳のためにもっと多くの仕事です。 – Bakuriu

+0

@Bakuriuありがとうございます説明。したがって、itemgetterの実装はcpythonでcコードとして最適化されています。オンラインドキュメンテーションで言及されているリファレンスPythonコードとして実装されているだけではありません。 – catchmeifyoutry

52
from operator import itemgetter 

sorted(your_list, key=itemgetter('name', 'age')) 
+2

'operator.itemgetter'がほぼ魔法のようなことをしているのだろうか?それはしません。これはタプル(この場合は長さ2)を返し、次に 'ソートされます。 –

0

代わりの一般的な解決法があります。これはdictの要素をキーと値でソートします。 それの利点 - キーを指定する必要はなく、一部のキーが一部の辞書にない場合でも機能します。

関連する問題