按照两个标准对Python列表进行sorting
我有从sorting的CSV创build的以下列表
list1 = sorted(csv1, key=operator.itemgetter(1))
我实际上想按照两个标准对列表进行sorting:首先是字段1中的值,然后是字段2中的值。我该怎么做?
喜欢这个:
import operator list1 = sorted(csv1, key=operator.itemgetter(1, 2))
回复这个死的线程进行归档。
使用lambda函数时无需导入任何东西。
以下按第一个元素list
,然后按第二个元素sorting。
sorted(list, key=lambda x: (x[0], -x[1]))
Python有一个稳定的sorting,所以如果性能不是问题,最简单的方法是按字段2sorting,然后再按字段1sorting。
这会给你想要的结果,唯一的问题是,如果它是一个大列表(或者你想要经常sorting)调用两次sorting可能是一个不可接受的开销。
list1 = sorted(csv1, key=operator.itemgetter(2)) list1 = sorted(list1, key=operator.itemgetter(1))
这样做也可以很容易地处理您想要某些列反向sorting的情况,只需在必要时包含“reverse = True”参数即可。
否则,您可以将多个parameter passing给itemgetter或手动构build一个元组。 这可能会更快,但有一个问题是,如果某些列想要反向sorting,它不能很好地概括(数字列仍然可以通过否定它们而被颠倒过来,但这会阻止sorting稳定)。
所以,如果你不需要任何反向sorting的列,可以为itemgetter提供多个参数,如果可能的话,列不是数字的,或者你想保持sorting稳定,进行多个连续的sorting。
编辑:对于有问题的评论者理解这个问题如何回答原始问题,下面是一个示例,它显示了sorting的稳定性如何确保我们可以对每个关键字进行单独sorting,并最终按照多个条件对数据进行sorting:
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
参数是如何保持名字顺序的,而简单sorting然后颠倒列表就会失去第三个sorting键所需的顺序。
def keyfunc(x): return tuple(x[1],x[2]) list1 = sorted(csv1, key=keyfunc)
假设你想对包含数字的string数组进行sorting,比如说
["date_2015-1-1", "date_2015-1-10", "date_2015-1-2"]
至
["date_2015-1-1", "date_2015-1-2", "date_2015-1-10"]
你可以这样做:
import re def sort_key(_str): return [ int(s) if s.isdigit() else s for s in re.split(r'(\d+)', _str) ] arr = ["date_2015-1-1", "date_2015-1-10", "date_2015-1-2"] sorted(arr, key=sort_key)