如何自定义排序字母数字列表?
How to custom sort an alphanumeric list?
我有以下列表
l = ['SRATT', 'SRATW', 'CRAT', 'CRA0', 'SRBTT', 'SRBTW', 'SRAT0', 'SRBT0']
我想按字母顺序排序,添加的规则是末尾包含数字(实际上始终为 0)的字符串必须位于最后一个完全按字母顺序排列的字符串之后(最后一个字母最多为 W)。
我该怎么做? (如果可能,使用像 sorted
这样的简单方法)
对于这个示例列表,期望的结果是
['CRAT', 'CRA0', 'SRATT', 'SRATW' , 'SRAT0', 'SRBTT', 'SRBTW', 'SRBT0']
例如以下无效
sorted(l, key=lambda x: x[-1].isdigit())
因为它将包含最终数字的字符串放在末尾,就像这样
['SRATT', 'SRATW', 'CRAT', 'SRBTT', 'SRBTW', 'CRA0', 'SRAT0', 'SRBT0']
底部的工作解决方案!
第一次尝试:
>>> l = ['SRATT', 'SRATW', 'CRAT', 'CRA0', 'SRBTT', 'SRBTW', 'SRAT0', 'SRBT0']
>>> sorted(l, key=lambda x: (x[:-1], x[-1].isdigit()))
['CRAT', 'CRA0', 'SRATT', 'SRATW', 'SRAT0', 'SRBTT', 'SRBTW', 'SRBT0']
更新
@StefanPochmann 说如果开头相同但最后 non-digit 个字符不同,这将失败。
我们可以在key的末尾添加额外的元素,也就是元素本身
>>> l = ['SRATT', 'SRATW', 'CRAT', 'CRA0', 'SRBTT', 'SRBTW', 'SRAT0', 'SRBT0', 'B', 'A']
>>> sorted(l, key=lambda x: (x[:-1], x[-1].isdigit(), x))
^
additional element
['A', 'B', 'CRAT', 'CRA0', 'SRATT', 'SRATW', 'SRAT0', 'SRBTT', 'SRBTW', 'SRBT0']
更新(最后,我希望如此)
@Demosthene 注意到第二次尝试没有成功,这是真的
因此可行的解决方案是选择元素末尾的任何数字(如果存在)并更改为超出字母和数字范围的符号,例如'{'
:
sorted(l, key=lambda x: ''.join((x[:-1], '{')) if x[-1].isdigit() else x)
或
sorted(l, key=lambda x: x[:-1] + '{' if x[-1].isdigit() else x)
如@StefanPochmann 所述。哪个可能更快。
您必须保留字符串的字母标准(减去最后一个元素),并引入另一个标准:以数字结尾。
sorted(l, key=lambda x: (x[:-1] ,x[-1].isdigit()))
更复杂但更可靠的方法:
sorted(l, key=lambda x: (x[:-1] if len(x)>1 and not x[-1].isdigit() else x,x[-1].isdigit() if x else False))
(修复了 Stefan 指出的极端情况,其中列表由 1 或 0 大小的元素或 ['AB', 'AA']
情况组成)
还有一个简单的方法,就是把0
当作Z
:
>>> sorted(l, key=lambda x: x.replace('0', 'Z'))
['CRAT', 'CRA0', 'SRATT', 'SRATW', 'SRAT0', 'SRBTT', 'SRBTW', 'SRBT0']
(我假设字符串前面没有零,如果有误请告诉我。)
我有以下列表
l = ['SRATT', 'SRATW', 'CRAT', 'CRA0', 'SRBTT', 'SRBTW', 'SRAT0', 'SRBT0']
我想按字母顺序排序,添加的规则是末尾包含数字(实际上始终为 0)的字符串必须位于最后一个完全按字母顺序排列的字符串之后(最后一个字母最多为 W)。
我该怎么做? (如果可能,使用像 sorted
这样的简单方法)
对于这个示例列表,期望的结果是
['CRAT', 'CRA0', 'SRATT', 'SRATW' , 'SRAT0', 'SRBTT', 'SRBTW', 'SRBT0']
例如以下无效
sorted(l, key=lambda x: x[-1].isdigit())
因为它将包含最终数字的字符串放在末尾,就像这样
['SRATT', 'SRATW', 'CRAT', 'SRBTT', 'SRBTW', 'CRA0', 'SRAT0', 'SRBT0']
底部的工作解决方案!
第一次尝试:
>>> l = ['SRATT', 'SRATW', 'CRAT', 'CRA0', 'SRBTT', 'SRBTW', 'SRAT0', 'SRBT0']
>>> sorted(l, key=lambda x: (x[:-1], x[-1].isdigit()))
['CRAT', 'CRA0', 'SRATT', 'SRATW', 'SRAT0', 'SRBTT', 'SRBTW', 'SRBT0']
更新
@StefanPochmann 说如果开头相同但最后 non-digit 个字符不同,这将失败。
我们可以在key的末尾添加额外的元素,也就是元素本身
>>> l = ['SRATT', 'SRATW', 'CRAT', 'CRA0', 'SRBTT', 'SRBTW', 'SRAT0', 'SRBT0', 'B', 'A']
>>> sorted(l, key=lambda x: (x[:-1], x[-1].isdigit(), x))
^
additional element
['A', 'B', 'CRAT', 'CRA0', 'SRATT', 'SRATW', 'SRAT0', 'SRBTT', 'SRBTW', 'SRBT0']
更新(最后,我希望如此)
@Demosthene 注意到第二次尝试没有成功,这是真的
因此可行的解决方案是选择元素末尾的任何数字(如果存在)并更改为超出字母和数字范围的符号,例如'{'
:
sorted(l, key=lambda x: ''.join((x[:-1], '{')) if x[-1].isdigit() else x)
或
sorted(l, key=lambda x: x[:-1] + '{' if x[-1].isdigit() else x)
如@StefanPochmann 所述。哪个可能更快。
您必须保留字符串的字母标准(减去最后一个元素),并引入另一个标准:以数字结尾。
sorted(l, key=lambda x: (x[:-1] ,x[-1].isdigit()))
更复杂但更可靠的方法:
sorted(l, key=lambda x: (x[:-1] if len(x)>1 and not x[-1].isdigit() else x,x[-1].isdigit() if x else False))
(修复了 Stefan 指出的极端情况,其中列表由 1 或 0 大小的元素或 ['AB', 'AA']
情况组成)
还有一个简单的方法,就是把0
当作Z
:
>>> sorted(l, key=lambda x: x.replace('0', 'Z'))
['CRAT', 'CRA0', 'SRATT', 'SRATW', 'SRAT0', 'SRBTT', 'SRBTW', 'SRBT0']
(我假设字符串前面没有零,如果有误请告诉我。)