我有一個路徑串列,在這里我將其簡化為類似但更簡單的字串:
paths = ['apple10/banana2/carrot1', 'apple10/banana1/carrot2', 'apple2/banana1', 'apple2/banana2', 'apple1/banana1', 'apple1/banana2', 'apple10/banana1/carrot1']
這些路徑需要按數字順序排序。第一個數字(蘋果)在搜索中是最重要的,其次是第二個。
一個可能很清楚的附加復雜性是某些路徑將具有資料所在的第三個目錄,而其他路徑則沒有。
路徑結構的 MWE 如下所示:
parent
|-----apple1
|------banana1
|----- data*
|------banana2
|----- data*
|-----apple2
|------banana1
|----- data*
|------banana2
|----- data*
|-----apple10
|------banana1
|-----carrot1
|-----data*
|-----carrot2
|-----data*
|------banana2
|----- carrot1
|-----data*
所需的輸出是:
paths = ['apple1/banana1', 'apple1/banana2', 'apple2/banana1', 'apple2/banana2', 'apple10/banana1/carrot1', 'apple10/banana1/carrot2','apple10/banana2/carrot1']
我正在努力弄清楚如何做到這一點。排序將不起作用,特別是因為數字會變成兩位數,而 10 會在 2 之前。
我已經看到另一個答案,它適用于字串串列中的單個數字。如何正確排序帶有數字的字串? 我沒能適應我的問題。
任何幫助將不勝感激。
uj5u.com熱心網友回復:
嘗試使用sorted,提供用于re從路徑中提取所有數字的自定義鍵:
import re
>>> sorted(paths, key=lambda x: list(map(int,re.findall("(\d )", x))))
['apple1/banana1',
'apple1/banana2',
'apple2/banana1',
'apple2/banana2',
'apple10/banana1/carrot1',
'apple10/banana1/carrot2',
'apple10/banana2/carrot1']
uj5u.com熱心網友回復:
除了@not_speshal 的回答:
根據您提供的問題的答案,如果您在路徑中的第一個單詞不一定是“蘋果”,您可以執行以下操作:
import re
def atoi(text):
return int(text) if text.isdigit() else text
def word_and_num_as_tuple(text):
return tuple( atoi(c) for c in re.split(r'(\d )', text) )
def path_as_sortable_tuple(path, sep='/'):
return tuple( word_and_num_as_tuple(word_in_path) for word_in_path in path.split(sep) )
paths = [
'apple10/banana2/carrot1',
'apple10/banana1/carrot2',
'apple2/banana1',
'apple2/banana2',
'apple1/banana1',
'apple1/banana2',
'apple10/banana1/carrot1'
]
paths.sort(key=path_as_sortable_tuple)
print(paths)
# And, of course, as a lambda one-liner:
paths.sort( key= lambda path: tuple( tuple( int(char_seq) if char_seq.isdigit() else char_seq for char_seq in re.split(r'(\d )', subpath) ) for subpath in path.split('/') ) )
它完全符合@MarcinCuprjak 的建議,但自動執行
uj5u.com熱心網友回復:
如果您可以將資料表示為元組而不是字串,那么事情會變得更容易:
paths = [('apple', 10, 'banana', 2, 'carrot', 1),
('apple', 10, 'banana', 1, 'carrot', 2),
('apple', 2, 'banana', 1),
('apple', 2, 'banana', 2),
('apple', 1, 'banana', 1),
('apple', 1, 'banana', 2),
('apple', 10, 'banana', 1, 'carrot', 1)
]
paths.sort(key=lambda item: (len(item), item))
print(paths)
輸出如你所愿,我認為:
[('apple', 1, 'banana', 1), ('apple', 1, 'banana', 2), ('apple', 2, 'banana', 1), ('apple', 2, 'banana', 2), ('apple', 10, 'banana', 1, 'carrot', 1), ('apple', 10, 'banana', 1, 'carrot', 2), ('apple', 10, 'banana', 2, 'carrot', 1)]
uj5u.com熱心網友回復:
使用以下工具:
itertools.groupbywithstr.isdigit將字符分組為連續的數字或非數字組;''.join從字符組中形成單詞;- 串列推導迭代組并過濾掉非數字組;
int如果單詞來自一組數字,則將它們轉換為整數。
將這些工具組合成一個tuple鍵sorted:
from itertools import groupby
paths = ['apple10/banana2/carrot1', 'apple10/banana1/carrot2', 'apple2/banana1', 'apple2/banana2', 'apple1/banana1', 'apple1/banana2', 'apple10/banana1/carrot1']
sorted(paths,
key=lambda s: tuple(int(''.join(group))
for are_digits,group in groupby(s, key=str.isdigit)
if are_digits))
# ['apple1/banana1', 'apple1/banana2', 'apple2/banana1', 'apple2/banana2', 'apple10/banana1/carrot1', 'apple10/banana1/carrot2', 'apple10/banana2/carrot1']
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/466046.html
上一篇:偏移兩個串列中的正數和負數并在Python中獲取其余數
下一篇:python中的矩陣(串列)
