以自然方式对字符串列表进行排序

时间:2019-01-17 16:09:24

标签: python python-3.x

我有以下内容:

sorted( ("A","a","b","B","CC","c"), key=lambda x: x.lower() )

哪个给:

['A', 'a', 'b', 'B', 'c', 'CC']

我如何这样排序:

['a', 'A', 'b', 'B', 'c', 'CC']

如果有两个相同的值,则低位形式首先出现-a在A之前。

我猜我正在做这样的事情:

sorted( ("A","a","b","B","CC","c"), key=lambda x: (x.lower(),x) )

但这在A之前给出A:

['A', 'a', 'B', 'b', 'c', 'CC']

我该如何做相反的事情?

更新

为进一步说明问题,以下字符串:[“ A”,“ a”,“ aA”,“ aa”]的排序应为:

["a","A","aa","aA"]

因此,在“ aA”之前的“ aa”和在“ aAa”之前的“ aaA”等。

所以:

lst = ["A","aA","aa","aaa","aAa","aaA","b","B","CC","c"]

应该排序为:

['A', 'aa', 'aA', 'aaa', 'aaA', 'aAa', 'b', 'B', 'c', 'CC']

4 个答案:

答案 0 :(得分:9)

您可以这样做:

lst = ["A","a","b","B","CC","c"]

result = sorted(lst, key= lambda x: (x.lower(), not x.islower()))
print(result)

输出

['a', 'A', 'b', 'B', 'c', 'CC']

更新

给出新的示例,您可以使用以下键:

lst = ["A", "aA", "aa", "aaa", "aAa", "aaA", "b", "B", "CC", "c"]
result = sorted(lst, key=lambda x: (x.lower(), ''.join(str(c.isupper()) for c in x)))
print(result)

输出

['A', 'aa', 'aA', 'aaa', 'aaA', 'aAa', 'b', 'B', 'c', 'CC']

对于另一个示例(["A","a","aA","aa"]),它给出:

['a', 'A', 'aa', 'aA']

答案 1 :(得分:5)

这是一种方法:

sorted( lst, key=lambda x: (x.lower(), *map(str.isupper, x)) )
#['A', 'aa', 'aA', 'aaa', 'aaA', 'aAa', 'b', 'B', 'c', 'CC']

首先按不区分大小写的字母排序。然后,对每个字符串的所有字符调用str.upper作为第二种排序条件。对于相同长度的字符串,这将使小写字母排在首位。

Python 2版本

以上语法仅在python3中有效,但是您可以等效地在python2中执行以下操作:

sorted( lst, key=lambda x: ((x.lower(),) + tuple(map(str.isupper, x))) )

答案 2 :(得分:0)

您可以这样做:

>>> sorted( ("A","a","b","B","CC","c"), key=lambda x: (x.lower() + str(x != x.lower()) ,x) )
['a', 'A', 'b', 'B', 'c', 'CC']

通过将字母的小写版本与实际字母进行比较来工作。如果小写字母匹配,则str(x != x.lower()0,否则为1

答案 3 :(得分:0)

以下是基于先前答案的解决方案:

sorted(lst, key= lambda x: (x.lower(), [c.isupper() for c in x]))

这似乎也可行:

sorted(lst, key= lambda x: (x.lower(), x.swapcase()))