【问题标题】:How to custom sort an alphanumeric list?如何自定义排序字母数字列表?
【发布时间】:2017-06-13 03:55:23
【问题描述】:

我有以下列表

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']

【问题讨论】:

  • 字符串是否包含除字母数字以外的其他字符?

标签: python string list sorting alphanumeric


【解决方案1】:

底部的工作解决方案

第一次尝试:

>>> 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 说这将失败,开头相同,最后一个非数字字符不同。

我们可以在键的末尾添加额外的元素,这将是元素本身

>>> 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 所说。这可能更快。

【讨论】:

  • 谢谢!将在几分钟内接受答案(所以现在不会让我这样做......)
  • @StefanPochmann 我已经更新了答案,它现在可以使用单个字符。谢谢。
  • @vishes_shell 它不只是失败了一个字符元素,这只是一个最小的例子。它也失败了,例如['ABCDEG', 'ABCDEF']。但你的修复也解决了这个问题。
  • @StefanPochmann 你是对的,对不起,你把你的例子放在错误的问题解释中。
  • @vishes_shell 我实际上发现了另一个问题;将元素'SRE' 添加到l 并使用sorted(l, key=lambda x: (x[:-1], x[-1].isdigit(), x)) 实际上将'SRE' 放在'SRATT' 之前。您将如何进行“绝对”字母排序?
【解决方案2】:

您必须保留字符串的字母标准(减去最后一个元素),并引入另一个标准:以数字结尾。

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'] 情况)

【讨论】:

  • 你的修复并没有真正修复它,现在它仍然失败,例如['AB', 'AA']
  • 你是对的。 “仅以 0 结尾”使这个答​​案显得多余。如果有任意位数就好了。
【解决方案3】:

这里还有一个简单的方法,把0当成Z

>>> sorted(l, key=lambda x: x.replace('0', 'Z'))
['CRAT', 'CRA0', 'SRATT', 'SRATW', 'SRAT0', 'SRBTT', 'SRBTW', 'SRBT0']

(我假设字符串前面没有零,如果有错请告诉我。)

【讨论】:

  • 确实OP说“最后是数字”然后说“它总是0”。
  • @Jean-FrançoisFabre 是的,但这并不排除其他地方的零。
  • 在这种情况下做:re.sub(r"\d$","Z",x)
  • @Jean-FrançoisFabre 是的,或re.sub(r"0$","Z",x)。但如果我的假设是正确的,我更喜欢非正则表达式的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-30
  • 2021-12-30
  • 1970-01-01
  • 2014-10-08
  • 1970-01-01
  • 2018-01-17
相关资源
最近更新 更多