1

うまくいけば、これは理にかなっています...

次の形式のタプルのリストがあります。

list_of_tuples = [('a', 1), ('b', 3), ('b', 2), ('a', 3)]

望ましい出力は

sorted_list_of_tuples = [('a', 1), ('b', 2), ('b', 3), ('a', 3)]

問題は、2 番目のエントリが増加し、最初のエントリが減少することです。

import operator as op     
sorted_list_of_tuples = sorted(list_of_tuples, key=op.itemgetter(2, 0))

もちろん、これは両方のフィールドを増加するようにソートします。これを行うためのかわいい (つまり、数行の) 方法が思いつきません。この種の並べ替えを簡単に達成する方法はありますか?

を使用して括弧内のリスト内包表記の要素を参照できることを覚えているよう_です。


はっきりしていないかもしれませんが、この場合は整数の方が重要です。その順序はリスト全体で増加するはずです。同点の場合 (つまり、2 番目のエントリが等しい場合)、'a' の前に 'b' が出現するようにします。

4

2 に答える 2

3

キーを英語で説明できる場合は、それを関数に翻訳してください。

2 番目のエントリが増加し、最初のエントリが減少するようにします。

したがって、鍵は次のとおりです。

def make_key(my_tuple):
    return my_tuple[1], -my_tuple[0]

もちろん、それ-は文字列ではうまくいかないので、もっと手の込んだものが必要です。

または、そうではないかもしれません...各タプルの最初の要素は文字列ですが、2 番目の要素は整数であるため、キー関数を否定し、否定を解除するために使用できますreverse

def make_key(my_tuple):
    return -my_tuple[1], my_tuple[0]

sorted_list_of_tuples = sorted(list_of_tuples, key=make_key, reverse=True)

いくつかのキーストロークを節約したい場合:

sorted_list_of_tuples = sorted(list_of_tuples,
                               key=lambda x: (x[1], x[0]), reverse=True)

ここで有効なトリックはこれだけではありません。たとえば、すべての文字列が 1 文字の文字列であるため、ord(x) < ord(y)iff x < y.

しかし、簡単なトリックが思い浮かばない場合もありますが、比較関数を作成する簡単な方法を思い付くことができます。より読みやすい場合は、次のようにします。

def compare_my_tuples(lhs, rhs):        
    if rhs[1] > lhs[0]: return 1
    elif rhs[1] < lhs[0]: return -1
    elif rhs[0] > lhs[0]: return -1
    elif rhs[0] < rhs[0]: return 1
    else: return 0

sorted_list_of_tuples = sorted(list_of_tuples, 
                               key=functools.cmp_to_key(compare_my_tuples))

または、もちろん、steveha の回答のように、2 つの種類に分割することもできます。(はい、2 倍の時間がかかるかもしれませんが、ほとんどのアプリでは、まったく違いはありません。)

于 2013-05-02T22:27:13.030 に答える
2

もちろん。Python の組み込みソートは「安定した」ソートです。だから、あなたがより重要にしたいソートを選択し、それを1秒間実行してください. 重要度の低いソートを実行してから、重要度の高い基準で再度ソートします。

作業コード:

import operator as op

list_of_tuples = [('a', 1), ('b', 3), ('b', 2), ('a', 3)]

list_of_tuples.sort(key=op.itemgetter(0), reverse=True)
list_of_tuples.sort(key=op.itemgetter(1))

assert list_of_tuples == [('a', 1), ('b', 2), ('b', 3), ('a', 3)]

巧妙なキー機能を思いついたら、すべてを 1 回のパスで実行できると思います。多分これ:

def custom_key_fn(tup):
    ch, n = tup # unpack tuple
    return (n, -ord(ch))

list_of_tuples = [('a', 1), ('b', 3), ('b', 2), ('a', 3)]
list_of_tuples.sort(key=custom_key_fn)

assert list_of_tuples == [('a', 1), ('b', 2), ('b', 3), ('a', 3)]
于 2013-05-02T22:26:00.373 に答える