オプション1:
key=lambda d:(d['rank']==0, d['rank'])
オプション 2:
key=lambda d:d['rank'] if d['rank']!=0 else float('inf')
デモ:
「1-2-3-4-0-0-0 のようにランク値で並べ替えたいと思います。」--オリジナルポスター
>>> sorted([0,0,0,1,2,3,4], key=lambda x:(x==0, x))
[1, 2, 3, 4, 0, 0]
>>> sorted([0,0,0,1,2,3,4], key=lambda x:x if x!=0 else float('inf'))
[1, 2, 3, 4, 0, 0]
追加コメント:
「私 (Python の初心者) に、それが何をしているのか説明していただけますか? これはラムダ関数であることがわかります。これは無名関数であることがわかっています。括弧内のビットは何ですか?」・OPコメント
索引付け/スライス表記:
itemgetter('rank')
関数と同じlambda x: x['rank']
ものです:
def getRank(myDict):
return myDict['rank']
[...]
はインデックス作成/スライス表記と呼ばれます。Python のスライス表記についての説明を参照してください。これsomeArray[n]
は、多くのプログラミング言語でインデックス作成に使用される一般的な表記ですが、[start:end]
またはの形式のスライスはサポートされない場合があることにも注意してください[start:end:step]
。
key=
vs cmp=
vs リッチ比較:
何が起こっているかについては、ソートアルゴリズムがどのようにkey
機能するかを指定する一般的な方法が 2 つありますcmp
。関数を使用すると、cmp
2 つの要素を比較する方法を任意に指定できます (入力: a
, b
; 出力:a<b
またはa>b
またはa==b
)。正当ではありますが、大きなメリットはありません (厄介な方法でコードを複製する必要があります)。cmp=
(洗練された、しかしおそらく過剰な方法で暗黙的に定義する方法については、「オブジェクトの豊富な比較」を参照してください。)
キー機能の実装:
残念ながら、0 は整数の要素であるため、自然な順序付けがあります。通常、0 は < 1,2,3 です... したがって、追加のルールを課したい場合は、リストを「上位レベル」でソートする必要があります。キーをタプルにすることでこれを行います: タプルは最初に最初の要素でソートされ、次に 2 番目の要素でソートされます。True は常に False の後に並べられるため、すべての True は Falses の後に並べられます。その後、通常どおりにソートされます: (True,1)<(True,2)<(True,3)<...
、(False,1)<(False,2)<...
、(False,*)<(True,*)
. 別の方法 (オプション 2) は、ランク 0 の辞書に無限大の値を割り当てるだけです。
より一般的な代替手段- オブジェクトの豊富な比較:
さらに一般的な解決策は、レコードを表すクラスを作成してから__lt__
、__gt__
、__eq__
、__ne__
、__gt__
、__ge__
およびその他すべての豊富な比較演算子を実装するか、それらのいずれかを実装してデコレータ__eq__
を使用することです。これにより、比較演算子 ( など)を使用するたびに、そのクラスのオブジェクトがカスタム ロジックを使用するようになります。関数は比較ソートでデフォルトで and 他の比較演算子を使用するため、これにより、ソート時の動作が自動化され、および 他の比較演算子を使用する他のインスタンスで動作が自動化されます。これは、ユースケースに応じて、過剰になる場合とそうでない場合があります。@functools.total_ordering
x=Record(name='Joe', rank=12)
y=Record(...)
x<y
sorted(...)
<
<
よりクリーンな代替手段- セマンティクスで 0 をオーバーロードしないでください:
ただし、1、2、3、4 などの後ろに 0 を置くのは少し人工的であることを指摘しておく必要があります。これが正当化されるかどうかは、rank=0 が本当に rank=0 を意味するかどうかに依存します。ランク= 0がランク= 1よりも実際に「低い」場合(ランク= 2よりも実際に「低い」...)。これが本当に当てはまる場合、あなたの方法はまったく問題ありません。そうでない場合は、'rank':...
を設定するのではなく、エントリを省略することを検討してください'rank':0
。次に、を使用して Lev Levitsky の回答'rank' in d
で並べ替えるか、次の方法で並べ替えることができます。
別のスキームのオプション 1:
key=lambda d: (not 'rank' in d, d['rank'])
別のスキームのオプション 2:
key=lambda d: d.get('rank', float('inf'))
補足: Python での無限の存在に依存することは、ほぼ境界線上にあるハックであり、前述のソリューション (タプル、オブジェクト比較)、Lev のfilter-then-concatenate ソリューション、さらには少し複雑なcmp
ソリューション(タイプアップ) のいずれかを作成します。ウィルソンによる)、他の言語へのより一般化が可能です。