Python按字母表顺序排序字符串,小写字母优先。

4
我希望使用Python按字母顺序对给定的字符串数组进行排序,但小写单词应该首先出现。
一个例子:
#!/usr/local/bin/python2.7
arr=['A','e','a','D','f','B']
arr.sort()
for s in arr: print s

输入:

A
e
a
D
f
B

输出(当前):

A
B
D
a
e
f

输出(应该是):
a
e
f
A
B
D

1
请注意,到目前为止所有答案都是按字母排序的(就像您的示例一样),而不是按单词排序的(就像您的问题一样)。 - georg
实际上,我的确可以对单词进行排序,只是我在示例中没有展示出来。 - SmeltQuake
@georg 错了。它们都可以对单词进行排序。按第一个字符排序,然后按第二个字符排序,直到整个单词排序完成。这里唯一的问题是标准排序具有不同于 OP 所需的排序索引。string.ascii_letters 具有此顺序。任何创建介于两者之间的解决方案都已过时。 - PascalVKooten
@PascalvKooten:测试示例:对['Abc','abc','aBc']进行排序应返回['abc','aBc','Abc'] - georg
@georg 我现在明白你的意思了,这确实完全改变了一切。 - PascalVKooten
6个回答

11

要对单词排序,而不仅仅是字母,请交换大小写:

>>> words = ['alpha', 'Alpha', 'aLpha', 'Bravo', 'bRavo']
>>> sorted(words)
['Alpha', 'Bravo', 'aLpha', 'alpha', 'bRavo']
>>> sorted(words, key=str.swapcase)
['alpha', 'aLpha', 'bRavo', 'Alpha', 'Bravo']

我承认错误:这确实应该是最佳答案(它是唯一正确的)。它也非常简洁。干得好(会尽快更改赞成)。 - PascalVKooten
这与Tanveer答案的第二部分相同,是正确的,甚至可以正确排序多个单词。点赞。 - polym

10
使用自定义键方法,检查项目是否不是.lower(),然后比较项目本身。对于'A''D''B'not x.islower()将返回True,对于其他情况则返回False,因为True > False,小写字母项将首先出现:
>>> arr = ['A','e','a','D','f','B']
>>> arr.sort(key=lambda x:(not x.islower(), x))
>>> arr
['a', 'e', 'f', 'A', 'B', 'D']

奇怪的是,它对我返回None - GLHF
@howaboutNO 不要将arr.sort的返回值赋给变量,它会直接在原始列表上进行排序。 - Ashwini Chaudhary
我认为值得一提的是,在Python中,False < True是成立的。这就是为什么(False, 'f') < (True, 'A') - ljk321
不使用import的好解决方案。 - PascalVKooten
@AshwiniChaudhary 我错过了那个。我的错。顺便说一下,优雅的解决方案。 - ljk321
尽管这个答案将多个单词排序错误(例如['a','P','v Q']的结果是['a','P','v Q']而不是['a','v Q','P']),但我并没有要求那样做,这个答案更符合我的需求 :)。 - polym

3
我们可以使用 string.ascii_letters 来获取每个字母的索引以进行排序。
arr = ['A','e','a','D','f','B']

import string

print sorted(arr, key=string.ascii_letters.index)

结果:

['a', 'e', 'f', 'A', 'B', 'D']

如果你想对原始的 arr 列表进行排序,可以使用内置函数sort

arr.sort(key=string.ascii_letters.index)
print arr

如果 arr 列表中的元素是单词而不是单个字母或字母,我们可以使用 str.swapcase 方法。

arr = ['Abc', 'abc', 'aBc']
print sorted(arr, key=str.swapcase)

产生:

['abc', 'aBc', 'Abc']

1
Lambda调用是多余的,.index已经是可调用的:arr.sort(key=string.ascii_letters.index) - Ashwini Chaudhary
@AshwiniChaudhary 非常感谢。最初我试图通过ordlambda进行排序,所以没有注意到这个问题。 - Tanveer Alam
@PascalvKooten 是的,对于单词,我们可以根据第一个字母进行排序。我已经在我的答案中包含了,请检查,谢谢。 - Tanveer Alam
@TanveerAlam 当tie-breaker晚于第2个字符时仍会出现错误。 - PascalVKooten
非常好的详细回答,点赞。虽然这个答案在多个单词排序时更好,但被接受的答案更符合我的需求。 - polym
显示剩余3条评论

2
一些测试表明,对于仅排序单个字符的情况,创建字典实际上是最有效的方法: python2.7:
from string import ascii_letters

d = {b:a for a, b  in enumerate(ascii_letters)}

In [34]: timeit  sorted(s, key=str.swapcase)
10 loops, best of 3: 32.6 ms per loop

In [35]: timeit sorted(s,key=lambda x: (not x.islower(),x))
10 loops, best of 3: 51.4 ms per loop

In [37]: timeit (sorted(s ,key=d.get))
10 loops, best of 3: 22.4 ms per loop

Python3.4:

In [4]: timeit sorted(s,key=lambda x: (not x.islower(),x))
10 loops, best of 3: 57.7 ms per loop

In [5]: timeit  sorted(s, key=str.swapcase)
10 loops, best of 3: 41.2 ms per loop

In [6]: timeit (sorted(s ,key=d.get))
10 loops, best of 3: 21.1 ms per loop

0

使用 Python 3.9

原地排序

arr=['A','e','a','D','f','B']
arr.sort(key=lambda x: (x.isupper(), x))
arr

输出

['a', 'e', 'f', 'A', 'B', 'D']

注意 - 使用sort方法时

异常不会被抑制 - 如果任何比较操作失败,整个排序操作将失败(并且列表可能会保留在部分修改的状态)。

对另一个变量进行排序并赋值,同时保持原始列表不变

arr=['A','e','a','D','f','B']
sorted_arr = sorted(arr, key=lambda x: (x.isupper(), x))
sorted_arr

输出

['a', 'e', 'f', 'A', 'B', 'D']

0

给定:包含字母和数字的字符串

目标:按照规则进行排序

  1. 先小写字母。
  2. 然后大写字母。
  3. 最后是数字(偶数优先,奇数次之)(优先级最低)。

    def func(l):
        if l.islower():
            return ord(l) - 32
        elif l.isupper():
            return ord(l) + 32
        elif l.isdigit():
            if int(l) % 2 == 0:
                return ord(l) + 200
            else:
                return ord(l) + 100
    
    print(*sorted(st, key=func), sep='')
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接