3

次のような文字列のすべてのリストを並べ替えたい:

list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
list2 = ['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002']

パターンに従って[ '3DT1_S##', '3DT1_noPN_DIS3D_S##', '3DT1_PN_noDIS3D_S##', '3DT1_PN_DIS3D_S##']

結果は次のようになります。

list1 = [ '3DT1_S001', '3DT1_noPN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_PN_DIS3D_S001']
list2 = [ '3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002']

sorted メソッドで少し遊んでみましたが、うまくいきませんでした。

助けはありますか?

4

4 に答える 4

4

必要な順序でタプルを返すキー関数を定義し、その関数をlike soのkeyパラメーターに渡すことができます。sorted

>>> def key_fn(x):
...     tags = x.split('_')
...     if tags[1][0] == 'S':
...         return (0, int(tags[1][1:]))
...     elif tags[1] == 'noPN':
...         return (1, int(tags[3][1:]))
...     elif tags[1] == 'PN':
...         if tags[2] == 'noDIS3D':
...             return (2, int(tags[3][1:]))
...         else:
...             return (3, int(tags[3][1:]))
... 
>>> list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
>>> sorted(list1, key=key_fn)
['3DT1_S001', '3DT1_noPN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_PN_DIS3D_S001']
于 2012-04-13T15:22:59.740 に答える
3

私の 2 セント... これには、順序を定義する「patternList」変数があります。これはおそらくこれを実装するための最も簡単な (最も人間が読みやすく、拡張可能な) 方法です: 面倒な if-else はありません。また、開始パターンが同じリスト項目は、文字列の残りの順に並べられます。

並べ替えの前list1.sort(key = myKey)に各リスト項目myKey関数が実行されることを意味します。関数は、通常の並べ替えが希望どおりに行われる方法でのみ、並べ替えの目的で並べmyKey替えられたリスト項目を変更します。出力ソート済みリストでは、元のリスト項目は使用されません (変更されたものではありません)。myKey

以下の例では、myKey 関数はリスト項目を 2 つの部分に分割し、最初の部分に patternList 変数に従って整数のラベルを付けます。通常の並べ替えは、返されたタプルを必要な方法で処理できます。

list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
list2 = ['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002', '3DT1_PN_DIS3D_S003', '3DT1_PN_DIS3D_S001']

def myKey(x):
    # create the 'order list' for starting pattern
    patternsList = [ '3DT1_S', '3DT1_noPN_DIS3D_S', '3DT1_PN_noDIS3D_S', '3DT1_PN_DIS3D_S']
    for i in range(len(patternsList)): # iterate patterns in order
        pattern = patternsList[i]
        if x.find(pattern) == 0: # check if x starts with pattern
            # return order value i and x without the pattern
            return (i, x.replace(pattern, '')) 

    # if undefined pattern is found, put it to first
    return (-1, x)

    # alternatively if you want undefind to be last
    # return (len(patternList)+1, x)


print list1
list1.sort(key = myKey)
print list1

print list2
list2.sort(key = myKey)
print list2
于 2012-04-14T22:19:14.020 に答える
1

このメソッドは、見つかった最初のパターンのインデックスでソートすることによって機能します。

>>> import re
>>> list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
>>> list2 = ['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002']
>>> patterns = [ '3DT1_S', '3DT1_noPN_DIS3D_S', '3DT1_PN_noDIS3D_S', '3DT1_PN_DIS3D_S']
>>> pattern = '|'.join('(%s)'%x for x in patterns)
>>> pattern #Creates a regex pattern with each pattern as a group in order
'(3DT1_S)|(3DT1_noPN_DIS3D_S)|(3DT1_PN_noDIS3D_S)|(3DT1_PN_DIS3D_S)'
>>> def sort_key(x):
        return re.match(pattern,x).lastindex
>>> list1, list2 = [sorted(l, key=sort_key) for l in (list1,list2)]
>>> list1
['3DT1_S001', '3DT1_noPN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_PN_DIS3D_S001']
>>> list2
['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002']
于 2012-04-13T15:31:10.393 に答える
-1

これは、並べ替えの前にリストをグループ化するために使用される「接頭辞」のリストを取るアプローチです。各項目は、一致する最初のプレフィックスのみに対応するグループに追加されます

list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
list2 = ['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002', '3DT1_S002']

prefixes = [ '3DT1_S', '3DT1_noPN_DIS3D_S', '3DT1_PN_noDIS3D_S', '3DT1_PN_DIS3D_S']

def f(l):
    result = []
    for p in prefixes:               # for each prefix, in order
        a = []                       # items in the group
        b = []                       # items not in the group
        for x in l:                  # for each item
            if x.startswith(p):      # does the item match the prefix?
                a.append(x)          # add it to the group
            else:  
                b.append(x)          # add it to the "rest"
        result.append(sorted(a))     # sort the group and save it for the result
        l = b                        # continue with the non-group elements
    return result

結果は次のとおりです。

>>> f(list1)
[['3DT1_S001'], ['3DT1_noPN_DIS3D_S001'], ['3DT1_PN_noDIS3D_S001'], ['3DT1_PN_DIS3D_S001']]
>>> f(list2)
[['3DT1_S002'], ['3DT1_noPN_DIS3D_S002'], ['3DT1_PN_noDIS3D_S002'], ['3DT1_PN_DIS3D_S002']]
于 2012-04-13T15:25:01.723 に答える