在Python中按元组第一个元素自然排序一个字母数字元组列表

4 投票
4 回答
3630 浏览
提问于 2025-04-16 22:22

之前有个StackOverflow的问题,讲的是怎么按字母和数字的顺序来排序字符串列表。我想要按元组的第一个元素,来对元组列表进行字母数字排序。

例子 1:

>>> sort_naturally_tuple([('b', 0), ('0', 1), ('a', 2)])
[('0', 1), ('a', 2), ('b', 0)]

例子 2:

>>> sort_naturally_tuple([('b10', 0), ('0', 1), ('b9', 2)])
[('0', 1), ('b9', 2), ('b10', 0)]

更新: 为了强调字母数字的排序,请查看例子 2。

4 个回答

1

正如其他人提到的,默认情况下,sorted函数会使用元组的第一个元素进行排序。如果你想改变这个默认的行为,可以指定一个用于比较的关键字。

sorted([('b', 0), ('0', 1), ('a', 2)])

这将返回和下面的内容一样:

sorted([('b', 0), ('0', 1), ('a', 2)], key=lambda item: item[0])

不过,如果你想按照第二个元素进行排序,可以试试:

sorted([('b', 0), ('0', 1), ('a', 2)], key=lambda item: item[1])
4

元组默认是按照它们的元素进行排序的,从第一个元素开始。所以只需要这样做:

L = [('b', 0), ('0', 1), ('a', 2)]
L.sort()
print L
# or create a new, sorted list
print sorted([('b', 0), ('0', 1), ('a', 2)])

你提到的问题是关于自然排序的,这和普通的(字母数字)排序是不同的。

假设你只想对第一个项目进行自然排序:

import re
def naturalize(item):
    # turn 'b10' into ('b',10) which sorts correctly
    m = re.match(r'(\w+?)(\d+)', item)
    return m.groups()
# now sort by using this function on the first element of the tuple:
print sorted(L, key=lambda tup: naturalize(tup[0]))
5

这里使用了另一个问题中的第二个答案,并进行了扩展,以支持对任何方法进行操作,从而获取键值:

import re
from operator import itemgetter

def sorted_nicely(l, key):
    """ Sort the given iterable in the way that humans expect."""
    convert = lambda text: int(text) if text.isdigit() else text
    alphanum_key = lambda item: [ convert(c) for c in re.split('([0-9]+)', key(item)) ]
    return sorted(l, key = alphanum_key)


print sorted_nicely([('b10', 0), ('0', 1), ('b9', 2)], itemgetter(0))

这个方法和之前的答案完全一样,只是扩展到了可以使用任何可调用的函数来处理项目。如果你只是想对字符串进行操作,可以用 lambda item: item;如果你想对列表、元组、字典或集合进行操作,可以用 operator.itemgetter(key_or_index_you_want);如果你想对类的实例进行操作,可以用 operator.attrgetter('attribute_name_you_want')

这会给出

[('0', 1), ('b9', 2), ('b10', 0)]

对于你的示例 #2。

撰写回答