首先对包含最长项目的列表进行排序

gor*_*tde 5 python sorting lambda python-3.x

我使用lambda来修改sort的行为.

sorted(list, key=lambda item:(item.lower(),len(item)))
Run Code Online (Sandbox Code Playgroud)

对包含元素的列表进行排序A1,A2,A3,A,B1,B2,B3,B,结果是A,A1,A2,A3,B,B1,B2,B3.

我预期的排序列表是A1,A2,A3,A,B1,B2,B3,B.

我已经尝试过包含len(item)for sort,但是没有用.如何修改lambda以便排序结果?

Ray*_*ger 6

这是一种方法:

>>> import functools
>>> def cmp(s, t):
    'Alter lexicographic sort order to make longer keys go *before* any of their prefixes'
    ls, lt = len(s), len(t)
    if ls < lt:   s += t[ls:] + 'x'
    elif lt < ls: t += s[lt:] + 'x'
    if s < t: return -1
    if s > t: return 1
    return 0

>>> sorted(l, key=functools.cmp_to_key(cmp))
['A1', 'A2', 'A3', 'A', 'B1', 'B2', 'B3', 'B']
Run Code Online (Sandbox Code Playgroud)

传统上,词典排序其他相同的前缀之后排序更长的字符串(即'abc'在'abcd'之前).

为了满足您的排序期望,我们首先通过添加较长字符串的剩余部分加上另一个字符来"修复"较短的字符串,使其成为两者中的较长者:

compare abc to defg     -->  compare abcgx to defg
compare a   to a2       -->  compare a2x to a2
Run Code Online (Sandbox Code Playgroud)

所述functools.cmp_to_key()工具然后转换该比较功能的关键功能.

这可能看起来像很多工作,但排序期望与内置的词典排序规则非常不一致.

FWIW,这是另一种写作方式,可能会或可能不会被认为更清晰:

def cmp(s, t):
    'Alter lexicographic sort order to make longer keys go *before* any of their prefixes'
    for p, q in zip(s, t):
        if p < q: return -1
        if q < p: return 1
    if len(s) > len(t): return -1
    elif len(t) > len(s): return 1
    return 0
Run Code Online (Sandbox Code Playgroud)

逻辑是:

  • 逐个字符地比较,直到找到另一对
  • 这个不同的对以传统方式确定排序顺序
  • 如果没有不同的对,那么最长的输入首先出现.
  • 如果没有不同的对并且长度相等,则字符串相等.

  • @ PM2Ring*functools.cmp_to_key*有一个简单的低开销纯python实现和更低开销(几乎无成本)的C实现.*functools.cmp_to_key*工具只是用于处理这种奇怪的cmp函数的特殊情况.在几乎所有其他情况下,cmp函数都是错误的做法(三向比较通常比布尔键函数更复杂,而cmp函数与O(n log n)相比,是关键函数,它们是O (n).SQL的ORDER BY子句使用键函数,它们解决了各种各样的现实问题. (3认同)

Jea*_*bre 1

我的第一个答案是:只是否定该len标准,仅根据该标准进行反转。

sorted(list, key=lambda item:(item.lower(),-len(item)))   # doesn't work!
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为 alpha 排序和长度之间存在冲突。Alpha 排序将小字符串放在前面。所以长度标准不起作用。

您需要合并这两个标准。彼此之间没有明确的优先顺序。

我找到了一种方法:首先计算字符串的最大长度,然后返回chr(127)字符串的填充(仅使用 ASCII 的最大字符)版本作为键,这样最小的字符串最后会被大字符填充:它们总是最后来。

l = ["A","B","A1","A2","A3","B1","B2","B3"]

maxlen = max(len(x) for x in l)
print(sorted(l, key=lambda item:item.lower()+chr(127)*(maxlen-len(item))))
Run Code Online (Sandbox Code Playgroud)

结果:

['A1', 'A2', 'A3', 'A', 'B1', 'B2', 'B3', 'B']
Run Code Online (Sandbox Code Playgroud)

顺便说一句,出于明显的原因,不要打电话给你的名单list