按两个字段对Python列表进行排序

我有一个从排序的CSV创建的以下列表

list1 = sorted(csv1, key=operator.itemgetter(1))

我实际上希望按照两个标准对列表进行排序:首先按字段1中的值,然后按字段2中的值排序。我该怎么做?


喜欢这个:

import operator
list1 = sorted(csv1, key=operator.itemgetter(1, 2))

回复这个死去的线程进行归档。

使用lambda函数时无需导入任何东西。
下面的排序list的第一个元素,然后通过第二个元素。

sorted(list, key=lambda x: (x[0], -x[1]))

Python有一个稳定的排序,所以假设性能不是问题,最简单的方法是按字段2排序,然后按字段1再次排序。

这会给你想要的结果,唯一的问题是,如果它是一个大列表(或者你想要经常排序),调用两次排序可能是不可接受的开销。

list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))

这样做也可以很容易地处理您想要某些列反向排序的情况,只需在必要时包含'reverse = True'参数即可。

否则,您可以将多个参数传递给itemgetter或手动构建元组。 这可能会更快,但存在的问题是,如果某些列想要反向排序(数字列仍然可以通过否定它们而被颠倒过来,但这会阻止排序稳定),它不能很好地概括。

因此,如果您不需要任何反向排序的列,请为itemgetter提供多个参数(如果可能的话),并且列不是数字,或者您想要保持排序稳定,并进行多次连续排序。

编辑:对于理解这个问题如何回答原始问题的评论者,下面是一个示例,它准确显示了排序的稳定性如何确保我们可以对每个关键字进行单独排序,并最终按照多个条件排序数据:

DATA = [
    ('Jones', 'Jane', 58),
    ('Smith', 'Anne', 30),
    ('Jones', 'Fred', 30),
    ('Smith', 'John', 60),
    ('Smith', 'Fred', 30),
    ('Jones', 'Anne', 30),
    ('Smith', 'Jane', 58),
    ('Smith', 'Twin2', 3),
    ('Jones', 'John', 60),
    ('Smith', 'Twin1', 3),
    ('Jones', 'Twin1', 3),
    ('Jones', 'Twin2', 3)
]

# Sort by Surname, Age DESCENDING, Firstname
print("Initial data in random order")
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred''')
DATA.sort(key=lambda row: row[1])

for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.''')
DATA.sort(key=lambda row: row[2], reverse=True)
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
''')
DATA.sort(key=lambda row: row[0])
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

这是一个可运行的例子,但为了节省运行它的人,输出是:

Initial data in random order
Jones      Jane       58
Smith      Anne       30
Jones      Fred       30
Smith      John       60
Smith      Fred       30
Jones      Anne       30
Smith      Jane       58
Smith      Twin2      3
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Jones      Twin2      3

First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Jones      Jane       58
Smith      Jane       58
Smith      John       60
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.
Smith      John       60
Jones      John       60
Jones      Jane       58
Smith      Jane       58
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.

Jones      John       60
Jones      Jane       58
Jones      Anne       30
Jones      Fred       30
Jones      Twin1      3
Jones      Twin2      3
Smith      John       60
Smith      Jane       58
Smith      Anne       30
Smith      Fred       30
Smith      Twin1      3
Smith      Twin2      3

特别需要注意的是,在第二步中reverse=True参数是如何保持名字顺序的,而简单排序然后颠倒列表会失去第三个排序键所需的顺序。

链接地址: http://www.djcxy.com/p/12211.html

上一篇: Sorting a Python list by two fields

下一篇: Can you detect business credit cards from the card number alone?