私はこのようなことをやろうとしています:
mylist.sort(key=lambda x: await somefunction(x))
しかし、私はこのエラーを受け取ります:
SyntaxError: 'await' outside async function
ラムダは非同期ではないので、これは理にかなっています。
async lambda x: ...
を使用しようとしましたが、SyntaxError: invalid syntax
がスローされます。
Pep 492 の状態:
非同期ラムダ関数の構文を指定できますが、この構成はこのPEPの範囲外です。
しかし、その構文がCPythonで実装されているかどうかはわかりませんでした。
非同期ラムダを宣言する方法、または非同期関数を使用してリストをソートする方法はありますか?
できません。 _async lambda
_はなく、キー関数は同期関数として呼び出され、待機されないため、キー関数としてlist.sort()
に渡すことはできません。簡単な回避策は、自分でリストに注釈を付けることです。
_mylist_annotated = [(await some_function(x), x) for x in mylist]
mylist_annotated.sort()
mylist = [x for key, x in mylist_annotated]
_
リスト内包表記のawait
式は、Python 3.6+でのみサポートされています。3.5を使用している場合は、次のことができます。
_mylist_annotated = []
for x in mylist:
mylist_annotated.append((await some_function(x), x))
mylist_annotated.sort()
mylist = [x for key, x in mylist_annotated]
_
Sven Marnachからの回答にはEdgeケースがあります。
同じ検索キーを生成するが、異なるため直接ソートできない2つのアイテムがあるリストをソートしようとすると、クラッシュします。
mylist = [{'score':50,'name':'bob'},{'score':50,'name':'linda'}]
mylist_annotated = [(x['score'], x) for x in mylist]
mylist_annotated.sort()
print( [x for key, x in mylist_annotated] )
あげる:
TypeError: '<' not supported between instances of 'dict' and 'dict'
幸い、私には簡単な解決策がありました。私のデータには並べ替え可能な一意のキーがあり、それを2番目のキーとして使用できます。
mylist = [{'score':50,'name':'bob','unique_id':1},{'score':50,'name':'linda','unique_id':2}]
mylist_annotated = [(x['score'], x['unique_id'], x) for x in mylist]
mylist_annotated.sort()
print( [x for key, unique, x in mylist_annotated] )
データに自然に一意の値がない場合は、並べ替える前に値を挿入できますか?おそらくuuid?
[〜#〜] edit [〜#〜]:コメントで提案されているように(ありがとう!)、operator.itemgetterを使用することもできます。
import operator
mylist = [{'score':50,'name':'bob'},{'score':50,'name':'linda'}]
mylist_annotated = [(x['score'], x) for x in mylist]
mylist_annotated.sort(key=operator.itemgetter(0))
print( [x for key, x in mylist_annotated] )