簡體   English   中英

基於子列表中的字母數字字符串的列表列表的自然排序?

[英]Natural sort of a list of lists based on an alphanumeric string within sub-list?

像泥一樣清澈,是嗎? 我將從一個例子開始...

my_list = [[4,'A4, A23, A3, A6', 'Description 1', 'Property 1'],
           [4,'B3, B35, B10, B22', 'Description 2', 'Property 2'],
           [6,'A1, A11, A10, A21, A2, A22', 'Description 3', 'Property 3']]

應該排序為:

>>>my_list:
[[6,'A1, A2, A10, A11, A21,  A22', 'Description 3', 'Property 3'] 
 [4,'A3, A4, A6, A23', 'Description 1', 'Property 1'],
 [4,'B3, B10, B22, B35', 'Description 2', 'Property 2']]

因此,我首先需要對每個子列表的第二個索引中的字符串進行自然排序,然后我需要根據子列表的第二個索引中的字符串對所有列表進行自然排序。 我整天都在撞牆,所以我發布任何嘗試的代碼都可能會導致錯誤。


也許我最初的示例案例不夠穩健,但這是我基於@Ashwini的代碼得到的結果:

[[ 1,   'C1', 'DW-00232'],
 [3,    'C11, C32, C46', 'DW-6546'],
 [7,    'C16, C17, C18, C19, C20, C21, C25', 'DW-545'],
 [5,    'C2, C3, C4, C5, C63', 'DW-7657'],
 [1,    'C26', 'DW-0056'],
 [2,    'C59, C60', 'DW-23424'],
 [5,    'C6, C13, C24, C30, C64', 'DW-5345']]

我希望輸出如下:

[[ 1,   'C1', 'DW-00232'],
 [5,    'C2, C3, C4, C5, C63', 'DW-7657'],
 [5,    'C6, C13, C24, C30, C64', 'DW-5345'],
 [3,    'C11, C32, C46', 'DW-6546'],
 [7,    'C16, C17, C18, C19, C20, C21, C25', 'DW-545'],
 [1,    'C26', 'DW-0056'],
 [2,    'C59, C60', 'DW-23424']]

球門柱不斷移動。 現在,我需要考慮某些字母數字組合在括號中的情況。 我需要在排序過程中忽略括號。

例:

[[ 1, 'C1', 'DW-00232'],
 [ 7, '(C21), C16, (C7), (C18), C19, C6, C65', 'DW-545'],
 [ 5, ' C4, (C2), C3, C10, (C5)', 'DW-7657']]

排序為:

[[ 1, 'C1', 'DW-00232'],
 [ 5, '(C2), C3, C4, (C5), C10', 'DW-7657'],    
 [ 7, 'C6, (C7), C16, (C18), C19, (C21), C65', 'DW-545']]

好的,一旦我仔細檢查了Ashwini的代碼,上述情況就是一個“簡單”的解決方案。 我根據他對鍵函數的處理方式(以下是我想要的方式對它進行排序,因此僅將每行排序不正確)添加了translate語句到他的自然排序函數中,如下所示。

        alphanum_key = (lambda key:
                        [convert(c.translate(None, punctuation + whitespace)) for c in re.split('([0-9]+)', key)])

使用此答案中natural_sort函數,您可以執行以下操作:

import re
from string import punctuation as punc, whitespace as wt
from pprint import pprint

def natural_sort(l): 
    #https://stackoverflow.com/a/4836734/846892
    convert = lambda text: int(text) if text.isdigit() else text.lower() 
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(l, key = alphanum_key)

def key(seq):                                           
    convert = lambda text: int(text) if text.isdigit() else text.lower() 
    return [convert(c.translate(None, punc+wt)) for c in re.split('([0-9]+)', seq)]
... 
>>> my_list = [[ 1,   'C1', 'DW-00232'],
 [3,    'C11, C32, C46', 'DW-6546'],
 [7,    'C16, C17, C18, C19, C20, C21, C25', 'DW-545'],
 [5,    'C2, C3, C4, C5, C63', 'DW-7657'],
 [1,    'C26', 'DW-0056'],
 [2,    'C59, C60', 'DW-23424'],
 [5,    'C6, C13, C24, C30, C64', 'DW-5345']]
>>> 
>>> new_lis = [x[:1] + [", ".join(natural_sort(x[1].split(', ')))] + x[2:]
                                                                for x in my_list]
>>> new_lis.sort(key = lambda x:key(x[1]))               
>>> pprint(new_lis)
[[1, 'C1', 'DW-00232'],
 [5, 'C2, C3, C4, C5, C63', 'DW-7657'],
 [5, 'C6, C13, C24, C30, C64', 'DW-5345'],
 [3, 'C11, C32, C46', 'DW-6546'],
 [7, 'C16, C17, C18, C19, C20, C21, C25', 'DW-545'],
 [1, 'C26', 'DW-0056'],
 [2, 'C59, C60', 'DW-23424']]
>>> 

默認的sort是使用內置的cmp比較我認為的元素,但是您可以這樣做,例如:

my_list.sort(key = lambda x: x[1])

這將指示它使用每個子列表的第一個元素作為比較鍵

編輯:沒有lambdas ...

from operator import itemgetter
my_list.sort(key = itemgetter(1))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM