2011-01-14 6 views
18

A question was asked here on SO、数分前に辞書キーを値に基づいて並べ替えます。operator.itemgetterを使用して辞書を並べ替える

私は数日前のソートの方法についてはちょうどoperator.itemgetterを読んで、それを試みることに決めましたが、それは動作していないようです。

質問に答えが表示されない場合は、operator.itemgetterとお試しください。

だから、辞書ました:

>>> mydict = { 'a1': ['g',6], 
      'a2': ['e',2], 
      'a3': ['h',3], 
      'a4': ['s',2], 
      'a5': ['j',9], 
      'a6': ['y',7] } 

私はこの試みた:

>>> l = sorted(mydict.itervalues(), key=operator.itemgetter(1)) 
>>> l 
[['e', 2], ['s', 2], ['h', 3], ['g', 6], ['y', 7], ['j', 9]] 

を、私はそれがしたいので、これは動作します。私は完全な辞書(mydict.itervalues())を持っていないので、私はこれを試してみました:

>>> complete = sorted(mydict.iteritems(), key=operator.itemgetter(2)) 

(私はそれが期待通りに)これは動作しません。

したがって、operator.itemgetterを使用してディクショナリをソートし、ネストされたキーと値のペアにitemgetterを呼び出します。

答えて

31
In [6]: sorted(mydict.iteritems(), key=lambda (k,v): operator.itemgetter(1)(v)) 
Out[6]: 
[('a2', ['e', 2]), 
('a4', ['s', 2]), 
('a3', ['h', 3]), 
('a1', ['g', 6]), 
('a6', ['y', 7]), 
('a5', ['j', 9])] 

キーパラメータは、常に一度に反復可能な要素(mydict.iteritems())から1つの項目が入力される関数です。 2 - - この場合、アイテムは、だから我々は、入力として('a2',['e',2])を取り、2

lambda (k,v): ...を返すことができる関数は一つの引数を取る匿名関数である必要はあり

('a2',['e',2]) 

のようなものかもしれませんtupleに変換し、kvに解凍します。したがって、lambda機能が当社商品に適用された場合、k'a2'v['e',2]となります。我々のアイテムに適用

lambda (k,v): operator.itemgetter(1)(v)従って、 operator.itemgetter(1)(['e',2])を返す「itemgets」lambda (k,v): operator.itemgetter(1)(v)は、Pythonでコーディングするための良い方法ではないこと2.

注ある['e',2]の2番目の項目を、。gnibblerが指摘するように、は、のそれぞれについてと再計算されます。それは非効率的です。 operator.itemgetter(1)を使用するポイントは、何度も適用できる関数を作成することです。そのたびにこの機能を再作成する必要はありません。 lambda (k,v): v[1]が読みやすくなり、より速く:

In [15]: %timeit sorted(mydict.iteritems(), key=lambda (k,v): v[1]) 
100000 loops, best of 3: 7.55 us per loop 

In [16]: %timeit sorted(mydict.iteritems(), key=lambda (k,v): operator.itemgetter(1)(v)) 
100000 loops, best of 3: 11.2 us per loop 
+0

これを説明してください: 'operator.itemgetter(1)(v))'? – user225312

+3

@A: 'operator.itemgetter(1)(v)'は 'v [1]'と同じです。あなたは 'a [b]'の出現を 'operator.itemgetter(b)(a)'に置き換えることができますが、これは*私があなたの質問を理解した方法ではありません:) –

+4

itemgetterの作成は比較的高価です。これは、dictの各キーに1つを作成します。 –

5

答えはありません。 operator.itemgetter(i)はそれはそれはd[i][j]ようsimething戻ることは決してありません

f = operator.itemgetter(i) 
f(d) == d[i] 

で、その引数の項目iを返す呼び出し可能を返します。あなたは本当に純粋に機能的なスタイルでこれを実行したい場合は、独自のcompose()機能書き込むことができます。

def compose(f, g): 
    return lambda *args: f(g(*args)) 

を、私はこれを行うにはお勧めしませんでした:)

sorted(mydict.iteritems(), key=compose(operator.itemgetter(1), 
             operator.itemgetter(1))) 

注意を使用します

+0

のような辞書を平坦化する必要があるだろうそれは明らかではありませんが、解決策です。私たちは彼がそれを更新するのを待つでしょう。 – user225312

5

itemgetterは(attrgetterはありませんが)ネストをサポートしていません

あなたはunutbu`があり `この

sorted(([k]+v for k,v in mydict.iteritems()), key=itemgetter(2)) 
+0

+1、かなり良い! – user225312