sorting a python list by two criteria
2016-06-18 17:45
1511 查看
Sorting
a Python list by two criteria
up vote59down votefavorite 20 | I have the following list created from a sorted csvlist1 = sorted(csv1, key=operator.itemgetter(1)) I would actually like to sort the list by two criteria: first by the value in field 1 and then by the value in field 2. How do I do this? python sorting
| ||
add a comment |
4 Answers
activeoldestvotesup vote66down voteaccepted | like this:import operator list1 = sorted(csv1, key=operator.itemgetter(1, 2))
| ||||||||||||||||||||
comment |
up vote100down vote | Replying to this dead thread for archive. No need to import anything when using lambda functions. The following sorts listby the first element, then by the second element. sorted(list, key=lambda x: (x[0], -x[1]))
| ||||||||||||||||||||
comments |
up vote8down vote | Python has a stable sort, so provided that performance isn't an issue the simplest way is to sort it by field 2 and then sort it again by field 1. That will give you the result you want, the only catch is that if it is a big list (or you want to sort it often) calling sort twice might be an unacceptable overhead. list1 = sorted(csv1, key=operator.itemgetter(2)) list1 = sorted(list1, key=operator.itemgetter(1)) Doing it this way also makes it easy to handle the situation where you want some of the columns reverse sorted, just include the 'reverse=True' parameter when necessary. Otherwise you can pass multiple parameters to itemgetter or manually build a tuple. That is probably going to be faster, but has the problem that it doesn't generalise well if some of the columns want to be reverse sorted (numeric columns can still be reversed by negating them but that stops the sort being stable). So if you don't need any columns reverse sorted, go for multiple arguments to itemgetter, if you might, and the columns aren't numeric or you want to keep the sort stable go for multiple consecutive sorts. Edit: For the commenters who have problems understanding how this answers the original question, here is an example that shows exactly how the stable nature of the sorting ensures we can do separate sorts on each key and end up with data sorted on multiple criteria: 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)) This is a runnable example, but to save people running it the output is: 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 Note in particular how in the second step the reverse=Trueparameter keeps the firstnames in order whereas simply sorting then reversing the list would lose the desired order for the third sort key.
| ||||||||||||||||||||
comments |
up vote3down vote | def keyfunc(x): return tuple(x[1],x[2]) list1 = sorted(csv1, key=keyfunc)
| ||||||||
|
相关文章推荐
- Python实现决策树
- python 爬虫学习之路
- 67. Add Binary [easy] (Python)
- 【contains-duplicate】leetCode python实现
- Python安装新的package
- Python学习笔记(While循环)
- 14. Longest Common Prefix [easy] (Python)
- threading in Python - 简单小例子
- 【leetCode】 Balanced Binary Tree python版实现
- python3 标准库 urllib.request
- 关于Python中函数默认参数的研究
- python笔记一_简单的基础
- python之流程控制语句
- 203. Remove Linked List Elements [easy] (Python)
- Python Collections Counter
- python 跨语言数据交互、json、pickle(序列化)、urllib、requests(爬虫模块)、XML。
- Python中找list中最大n个数的包heapq.nlargest
- 257. Binary Tree Paths [easy] (Python)
- 双色球 python
- 搞不懂 numpy.sum 请过来