2016-01-14 17 views
6

私は複数の基準で並べ替えたい項目のリストを持っています。高度なカスタムソート

考えると、入力リスト:

cols = [ 
    'Aw H', 
    'Hm I1', 
    'Aw I2', 
    'Hm R', 
    'Aw R', 
    'Aw I1', 
    'Aw E', 
    'Hm I2', 
    'Hm H', 
    'Hm E', 
] 

の規準:

  • フム>おやおや
  • I> R> H> E

出力は次のようになります。

cols = [ 
    'Hm I1', 
    'Aw I1', 
    'Hm I2', 
    'Aw I2', 
    'Hm R', 
    'Aw R', 
    'Hm H', 
    'Aw H', 
    'Hm E', 
    'Aw E' 
] 

私はこの機能が組み込みのsorted()に渡される必要があることを知っていますが、実際にどのように書き込むのですか?

+0

http://stackoverflow.com/questions/14208256/sort-a-list-with-a-custom-order-in-pythonの可能な重複やhttp://stackoverflow.com/questions/3624323/python-how-to-custom-order-a-list – SIslam

答えて

7

あなたが書くことができますキーの関数で、優先度別にソートされたそれぞれの部分を持つtupleを返します。

def k(s): 
    m = {'I':0, 'R':1, 'H':2, 'E':3} 
    return m[s[3]], int(s[4:] or 0), -ord(s[0]) 

cols = [ 
    'Aw H', 
    'Hm I1', 
    'Aw I2', 
    'Hm R', 
    'Aw R', 
    'Aw I1', 
    'Aw E', 
    'Hm I2', 
    'Hm H', 
    'Hm E', 
] 

結果:

>>> for i in sorted(cols, key=k): 
...  print(i) 
... 
Hm I1 
Aw I1 
Hm I2 
Aw I2 
Hm R 
Aw R 
Hm H 
Aw H 
Hm E 
Aw E 

tuple S並べ替え、最初の要素が最初に比較されます。それらが同じ場合、tupleは2番目の要素でソートされます。これは、通常の単語がアルファベット順にソートされる方法に似ています。

最初に、'I'のすべての要素をまとめて、次に'R'などとしたいので、最初にそれを入れます。そのために、各文字に希望の優先順位を付ける辞書を定義します。その文字列(文字列の4番目の文字、s[3])をその辞書で検索すると、そのキーの最初の部分があります。

次に、その文字の後の数字が必要です。このために、短絡を使用して5文字目以降の文字を取得します(s[4:])。何もない場合は0を取得します。私たちはintにそれを送ります。それは、'12'の後に'2'となる数字として評価されます。

最後に、最初の2つの部分が同じ場合、項目は最初の文字に基づいてソートされます。これが単純なソートの場合は、reverse=Trueと指定できます。この部分が数字だった場合、私たちはそれを否定することができます。その文字をord()の数字に変換してから、それを否定します。

の場合、結果はたとえば(0, 2, -65)のキーになります。

1

次のように動作します:

cols = [ 
    'Aw H', 
    'Hm I1', 
    'Aw I2', 
    'Hm R', 
    'Aw R', 
    'Aw I1', 
    'Aw E', 
    'Hm I2', 
    'Hm H', 
    'Hm E', 
] 

def compare(x, y): 
    x1, x2 = x.split(' ') 
    y1, y2 = y.split(' ') 

    order = ['I1', 'I2', 'R', 'H', 'E'] 

    if order.index(x2) < order.index(y2): 
     return -1 
    elif order.index(x2) > order.index(y2): 
     return 1 
    else: 
     if x1 == 'Hm' and y1 == 'Aw': 
      return -1 
     elif x1 == 'Aw' and y1 == 'Hm': 
      return 1 
    return 0 

cols.sort(compare) 
print(cols) 

出力

['Hm I1', 'Aw I1', 'Hm I2', 'Aw I2', 'Hm R', 'Aw R', 'Hm H', 'Aw H', 'Hm E', 'Aw E'] 
1

おやおや、フムとE、H、Rを比較するために、私はなど、あなたには2つの辞書を定義することができます今度は、各文字列を3つの要素に分解する必要があります。1.(AwまたはHm)2.(EまたはHまたはRまたはI)3.整数

は、今、私たちは私たちの主要な機能からタプルを返すことができ辞書から、これらのコンポーネントと対応する値を使用して:

>>> import re 
>>> from pprint import pprint 
>>> map_1 = {'Aw': 0, 'Hm': 1} 
>>> map_2 = {'E': 0, 'H': 1, 'R': 2, 'I': 3} 
>>> pattern = re.compile(r'(Aw|Hm)\s([EHRI])(\d*)') 
>>> def key_func(x): 
    a, b, c = pattern.search(x).groups() 
    return map_2[b], -int(c) if c else 0, map_1[a] 
... 
>>> pprint(sorted(cols, key=key_func, reverse=True)) 
['Hm I1', 
'Aw I1', 
'Hm I2', 
'Aw I2', 
'Hm R', 
'Aw R', 
'Hm H', 
'Aw H', 
'Hm E', 
'Aw E'] 
1

何かを作成しましょう:

手紙にポイントを割り当てるのはどうですか?

def custom_sort(string): 
    value_dict = {'I':400 ,'R': 300,'H': 200,'E':100, 'Hm': 50, 'Aw':40} 
    s = string.split() 
    points = value_dict[s[0]] + value_dict[s[1][0]] 
    if -len(s[1])>1: 
     points -= int(s[1][1:]) 
    return -points 

cols = [ 
    'Aw H', 
    'Hm I1', 
    'Aw I2', 
    'Hm R', 
    'Aw R', 
    'Aw I1', 
    'Aw E', 
    'Hm I2', 
    'Hm H', 
    'Hm E', 
] 

print sorted(cols, key=custom_sort)