Python排序 - 半忽略大小写(a,aa,A,AA,b,bb,B,BB ...)

min*_*ion 6 python sorting

如何对列表进行排序以达到:

['a', 'aa', 'aaa', 'A', 'AA', 'AAA', 'b', 'bb', 'bbb', 'B', 'BB', 'BBB']
Run Code Online (Sandbox Code Playgroud)

为方便起见,假设它的洗牌版本:

['bb', 'a', 'B', 'BB', 'AAA', 'BBB', 'b', 'aa', 'aaa', 'A', 'AA', 'bbb']
Run Code Online (Sandbox Code Playgroud)

我试图通过忽略大小写进行排序:

l = sorted(l, key=lambda x: x.lower())
Run Code Online (Sandbox Code Playgroud)

结果 ['a', 'A', 'aa', 'AA', 'aaa', 'AAA']


从下面的答案,混合情况有两种解决方案,我不确定哪种更好.

L = ['ABC1', 'abc1', 'ABC2', 'abc2', 'Abc']
l = sorted(L, key=lambda x: "".join([y.lower() + y.swapcase() for y in x]))
print(l)
l = sorted(L, key=lambda x: [(c.lower(), c.isupper()) for c in x])
print(l)
Run Code Online (Sandbox Code Playgroud)

Eug*_*ash 9

您可以使用sorted()自定义键功能:

>>> L = ['bb', 'a', 'B', 'BB', 'AAA', 'BBB', 'b', 'aa', 'aaa', 'A', 'AA', 'bbb']
>>> sorted(L, key=lambda x: (x[0].lower(), x[0].isupper(), len(x)))
['a', 'aa', 'aaa', 'A', 'AA', 'AAA', 'b', 'bb', 'bbb', 'B', 'BB', 'BBB']
Run Code Online (Sandbox Code Playgroud)

这是通过首先比较每个元素的第一个小写字符,然后是元素的大小写,最后是它的长度来实现的.

PS要处理混合大小写和混合字符元素,您需要比较单个字符的元组,例如:

>>> L = ['ab', 'aA', 'bb', 'a', 'B', 'BB', 'b', 'aa', 'A', 'AA']
>>> sorted(L, key=lambda x: [(c.lower(), c.isupper()) for c in x])
['a', 'aa', 'aA', 'ab', 'A', 'AA', 'b', 'bb', 'B', 'BB']
Run Code Online (Sandbox Code Playgroud)

  • 这可能会在`aa`之前排序`ab`,这看起来很奇怪.我认为在那里某处有"x"会更有意义. (2认同)

hil*_*lem 6

TLDR

result = sorted(lst, key=lambda s: [(c.lower(), c.isupper()) for c in s])
Run Code Online (Sandbox Code Playgroud)

您可以将每个字符串转换为元组列表,每个字符一个.角色的元组c采用一种形式(c.lower(), c.isupper()).通常的列表比较给出了您想要的排序.

lst = ["a", "aa", "aaa", "A", "AA", "AAA", "b", "bb", "bbb", "B", "BB", "BBB"]

lsts = [[(c.lower(), c.isupper()) for c in s] for s in lst]

# [[('a', False)],
# [('a', False), ('a', False)],
# [('a', False), ('a', False), ('a', False)],
# [('a', True)],
# [('a', True), ('a', True)],
# [('a', True), ('a', True), ('a', True)],
# [('b', False)],
# [('b', False), ('b', False)],
# [('b', False), ('b', False), ('b', False)],
# [('b', True)],
# [('b', True), ('b', True)],
# [('b', True), ('b', True), ('b', True)]]

res = ["".join(c.upper() if u else c for c, u in ls) for ls in lsts]
Run Code Online (Sandbox Code Playgroud)

恢复结果:

['a', 'aa', 'aaa', 'A', 'AA', 'AAA', 'b', 'bb', 'bbb', 'B', 'BB', 'BBB']
Run Code Online (Sandbox Code Playgroud)

请注意,有许多不同的方法来命令与OP原始示例一致的混合大小写元素.这种方法是我能想到的唯一合理的方法,它来自反对称的顺序关系.特别是,这种类型不承认不相等的等效元素.

例如,['aAa', 'aaA']并且['aaA', 'aAa']会导致相同的输出['aaA', 'aAa'].