web-dev-qa-db-ja.com

リスト内包表記を1つのステートメントに並べ替える

今朝スクリプトを書いているときに、予期していなかったことに気づきました。リスト内包表記を使用して、すべてを1つのステートメントに並べ替えようとすると、驚くべき結果が得られました。次のコードは私の一般的な使用例を要約していますが、この質問のために簡略化されています。

Transaction = namedtuple('Transaction', ['code', 'type'])

my_list = [Transaction('code1', 'AAAAA'), Transaction('code2', 'BBBBB'), Transaction('code3', 'AAAAA')]

types = ['AAAAA', 'CCCCC']

result = [trans for trans in my_list if trans.type in types].sort(key = lambda x: x.code)

print result

出力:

None

内包表記を使用してリストを作成し、事後に並べ替えると、すべて問題ありません。なぜこれが起こるのか興味がありますか?

21
donopj2

メソッドlist.sort()はリストを適切にソートしており、すべての変更メソッドと同様にNoneを返します。組み込み関数 sorted() を使用して、新しいソート済みリストを返します。

_result = sorted((trans for trans in my_list if trans.type in types),
                key=lambda x: x.code)
_

_lambda x: x.code_の代わりに、少し高速なoperator.attrgetter("code")を使用することもできます。

41
Sven Marnach

リストで_.sort_を呼び出すと、Noneが返されます。この結果がresultに割り当てられることは完全に理にかなっています。

つまり、リスト内包表記を使用して匿名でリストを作成し、_.sort_を呼び出すと、_.sort_呼び出しの結果がresult変数に格納されている間、リストは失われます。

他の人が言っているように、リストを返すにはsorted()組み込み関数を使用する必要があります。 (sorted()は、リストのソートされたコピーを返します。)

4
Platinum Azure

sorted組み込み関数が必要です。 sortメソッドは、リストをその場でソートし、Noneを返します。

result = sorted([trans for trans in my_list if trans.type in types],key = lambda x: x.code)

これは、次の方法で少し改善できます。

import operator
result = sorted( (trans for trans in my_list if trans.type in types ), key=operator.attrgetter("code"))
0
mgilson