史上最全關於sorted函式的10條總結
題圖:Google搜尋
sorted
用於對集合進行排序(這裡說的集合是對可迭代物件的一個統稱,他們可以是列表、字典、set、甚至是字串),它的功能非常強大,本文將深入淺出地介紹 sorted 的各種使用場景。
1、預設情況,sorted 函式將按列表升序進行排序,並返回一個新列表物件,原列表保持不變,最簡單的排序
>>> nums = [3,4,5,2,1]
>>> sorted(nums)
[1, 2, 3, 4, 5]
2、降序排序,如果要按照降序排列,只需指定引數 reverse=True 即可
>>> sorted(nums, reverse=True)
[5, 4, 3, 2, 1]
3、如果要按照某個規則排序,則需指定引數 key
, key 是一個函式物件,例如字串構成的列表,我想按照字串的長度來排序
>>> chars = ['Andrew', 'This', 'a', 'from', 'is', 'string', 'test']
>>> sorted(chars, key=len)
['a', 'is', 'from', 'test', 'This', 'Andrew', 'string']
len
是內建函式,sorted 函式在排序的時候會用len去獲取每個字串的長度來排序。 有些人可能使用匿名函式 key=lambda x: len(x) ,其實多此一舉。
4、如果是一個複合的列表結構,例如由元組構成的列表,要按照元組中的第二個元素排序,那麼可以用 lambda 定義一個匿名函式
>>> students = [('zhang', 'A'), ('li', 'D'), ('wang', 'C')]
>>> sorted(students, key=lambda x: x[1])
[('zhang', 'A'), ('wang', 'C'), ('li', 'D')]
這裡將按照字母 A-C-D 的順序排列。
5、如果要排序的元素是自定義類,例如Student類按照年齡來排序,則可以寫成
>>> class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age
def __repr__(self):
return repr((self.name, self.grade, self.age))
>>> student_objects = [
Student('john', 'A', 15),
Student('jane', 'B', 12),
Student('lily', 'A', 12),
Student('dave', 'B', 10), ]
>>> sorted(student_objects, key=lambda t:t.age)
[('dave', 'B', 10), ('jane', 'B', 12), ('lily', 'A', 12), ('john', 'A', 15)]
6、和資料庫的排序一樣,sorted 也可以根據多個欄位來排序,例如我有先要根據age排序,如果age相同的則根據grade排序,則可以使用元組:
>>> sorted(student_objects, key=lambda t:(t.age, t.grade))
[('dave', 'B', 10), ('lily', 'A', 12), ('jane', 'B', 12), ('john', 'A', 15)]
7、前面碰到的排序場景都是建立在兩個元素是可以互相比較的前提下,例如數值按大小比較, 字母按順序比較,如果遇到本身是不可比較的,需要我們自己來定義比較規則的情況如何處理呢?
舉個簡單的例子:
>>> nums = [2, 1.5, 2.5, '2', '2.5']
>>> sorted(nums)
TypeError: '<' not supported between instances of 'str' and 'int'
一個整數列表中,可能有數字,字串,在Python3中,字串與數值是不能比較的,而Python2中任何型別都可以比較,這是兩個版本中一個很大的區別:
# python2.7
>>> "2.5" > 2
True
# python3.6
>>> "2.5" > 2
TypeError: '>' not supported between instances of 'str' and 'int'
我們需要使用 functools 模組中的 cmp_to_key 來指定比較函式是什麼。
import functools
def compare(x1, x2):
if isinstance(x1, str):
x1 = float(x1)
if isinstance(x2, str):
x2 = float(x2)
return x1 - x2
>>>sorted(nums, key=functools.cmp_to_key(compare))
[1.5, 2, '2', 2.5, '2.5']
8、關於 sorted 函式,Python2和Python3之間的區別是Python2中的sorted 可以指定cmp關鍵字引數,就是當遇到需要自定義比較操作的資料可以通過 cmp=compare 來實現,不需要像Python3中還需要匯入functools.cmp_to_key實現。
nums = [2, 1.5, 2.5, '2', '2.5']
def compare(x1, x2):
if isinstance(x1, str):
x1 = float(x1)
if isinstance(x2, str):
x2 = float(x2)
return 1 if x1 - x2 > 0 else -1 if x1 - x2 < 0 else 0
>>> sorted(nums, cmp=compare)
[1.5, 2, '2', 2.5, '2.5']
其實,在Python2中,上面這種情況你不指定cmp,預設也會按照這種方式排序,記住,Python2中,任何東西(不同型別之間)都可以比較,而Python3只有同型別資料可以比較。
9、 對於集合構成的列表,有一種更高效的方法指定這個key
>>> from operator import itemgetter
>>> sorted(students, key=itemgetter(1))
[('zhang', 'A'), ('wang', 'C'), ('li', 'D')]
10、同樣的,對於自定義類,也有一種更高效的方法指定key
>>> from operator import attrgetter
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
如果參與排序的欄位有兩個怎麼辦,你可以這樣:
>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
以上是關於 sorted 函式的全部。留給大家的作業:sorted 函式的實現原理是什麼?
相關文章
- 關於linux下system()函式的總結Linux函式
- C++ 序列操作函式最全總結C++函式
- 吐血總結|史上最全的MySQL學習資料!!MySql
- 內建函式sorted的10個小tips函式
- 史上最全 Redis 高可用解決方案總結Redis
- 關於字串的功能函式小結字串函式
- 史上最全排序演算法總結!建議收藏排序演算法
- python中關於時間和日期函式的常用計算總結Python函式
- tensorflow相關函式學習總結函式
- python---之sorted函式Python函式
- python內建函式——sortedPython函式
- python sorted()函式的引數用法Python函式
- MySQL 字串擷取相關函式總結MySql字串函式
- Python之operator.itemgetter函式和sorted函式Python函式
- 總結常用的字串函式字串函式
- Sigmoid函式總結Sigmoid函式
- 這可能是史上最全Redis高可用解決方案總結Redis
- 12.4、python內建函式—sortedPython函式
- 關於Android room 時間函式條件的坑 給需要的人AndroidOOM函式
- lambda匿名函式sorted排序函式filter過濾函式map對映函式函式排序Filter
- 【資源】史上最全資料集彙總
- 關於count函式的理解函式
- 關於近期的總結
- spark中的聚合函式總結Spark函式
- JS 中的函式 this 指向總結JS函式
- mysql日期函式總結MySql函式
- PHP常用函式總結PHP函式
- 關於建構函式與解構函式的分享函式
- 關於函式指標函式指標
- mysql關於variable的總結MySql
- sqlserver關於always on的總結SQLServer
- php 驗證格式的函式總結PHP函式
- 史上最全的WebSettings說明Web
- Python函式引數總結Python函式
- mysql函式全面總結KSVMMySql函式
- 史上最全的中高階JAVA工程師-面試題彙總Java工程師面試題
- 以下關於CISC和RISC的敘述中,錯誤的是()【最全!最詳細總結!】
- ES6新特性總結之let和const--史上最全最簡潔