最簡單的排序方式是使用已排序(清單) 函式,這個函式會擷取清單,並傳回包含這些元素的新清單。原始清單不會改變。
a = [5, 1, 4, 3] print(sorted(a)) ## [1, 3, 4, 5] print(a) ## [5, 1, 4, 3]
最常將清單傳遞至 Sort() 函式,但實際上它也可以當做任何可疊代的集合輸入內容。舊版 list.sort() 方法會是下文的詳細說明。相較於 Sort(),排序() 函式更容易使用,因此我建議使用 saved()。
透過選用引數可以自訂 Sort() 函式。Sort() 的選用引數 back=True,例如 Sort(list, back=True),會反向排序。
strs = ['aa', 'BB', 'zz', 'CC'] print(sorted(strs)) ## ['BB', 'CC', 'aa', 'zz'] (case sensitive) print(sorted(strs, reverse=True)) ## ['zz', 'aa', 'CC', 'BB']
使用鍵=自訂排序
如果是更複雜的自訂排序方式,Sort() 會使用選用的 "key= 來指定「key」函式,在比較前轉換每個元素。鍵函式採用 1 個值並傳回 1 個值,而傳回的「proxy」值用於排序中的比較項目。
舉例來說,如果是字串清單,指定 key=len (內建的 len() 函式) 就能按照長度,從最短到最長字串排序字串。排序會呼叫每個字串的 len(),取得 Proxy 長度值的清單,然後依照這些 Proxy 值排序。
strs = ['ccc', 'aaaa', 'd', 'bb'] print(sorted(strs, key=len)) ## ['d', 'bb', 'ccc', 'aaaa']
再舉一個例子,指定「str.lower」做為索引鍵函式,這個方式可強制排序作業視為相同的大小寫:
## "key" argument specifying str.lower function to use for sorting print(sorted(strs, key=str.lower)) ## ['aa', 'BB', 'CC', 'zz']
您也可以傳入自己的 MyFn 做為鍵函式,如下所示:
## Say we have a list of strings we want to sort by the last letter of the string. strs = ['xc', 'zb', 'yd' ,'wa'] ## Write a little function that takes a string, and returns its last letter. ## This will be the key function (takes in 1 value, returns 1 value). def MyFn(s): return s[-1] ## Now pass key=MyFn to sorted() to sort by the last letter: print(sorted(strs, key=MyFn)) ## ['wa', 'zb', 'xc', 'yd']
如要進行更複雜的排序 (例如先依姓氏排序,再依名字排序),您可以使用 itemgetter 或 attrgetter 函式,例如:
from operator import itemgetter # (first name, last name, score) tuples grade = [('Freddy', 'Frank', 3), ('Anil', 'Frank', 100), ('Anil', 'Wang', 24)] sorted(grade, key=itemgetter(1,0)) # [('Anil', 'Frank', 100), ('Freddy', 'Frank', 3), ('Anil', 'Wang', 24)] sorted(grade, key=itemgetter(0,-1)) #[('Anil', 'Wang', 24), ('Anil', 'Frank', 100), ('Freddy', 'Frank', 3)]
order() 方法
清單上的 Sort() 方法除了可依遞增順序排序 (例如 list.sort()),也會以遞增順序排列清單。排序方法會變更基礎清單並傳回 None,因此請使用以下程式碼:
alist.sort() ## correct alist = blist.sort() ## Incorrect. sort() returns None
上列是 {0}Sort() 十分常見的誤解,通常「不會傳回*」已排序的清單。order() 方法必須在清單上呼叫;這個方法不適用於任何可列舉集合 (但上面的 Sort() 函式可處理任何項目)。order() 方法會預先排序出已排序的函式,因此您可能會在較舊的程式碼中看到該函式。origin() 方法不必建立新的清單,因此如果要排序的元素已在清單中,可以更快一點。
元組
元組是固定大小的元素群組,例如 (x, y) 協調項目。元組就像清單,只是它們無法變更,而且不會改變大小 (元組並非完全不可變更,因為內含的其中一個元素可以變動)。元組在 Python 中扮演了一種「結構」角色,方便您傳遞邏輯固定、大小固定的值組合。需要傳回多個值的函式只能傳回值的元組。例如,如果要建立包含 3D 座標的清單,那麼自然的 Python 表示法就是一元組,其中每個元組是大小 3,其中每個元組代表一個 (x, y, z) 群組,
如要建立元組,只要列出括號內的值,並以半形逗號分隔即可。「空白」元組只是一對空白括號。存取元組中的元素就像清單一樣,len()、[ ]、for、in 等都是一樣。
tuple = (1, 2, 'hi') print(len(tuple)) ## 3 print(tuple[2]) ## hi tuple[2] = 'bye' ## NO, tuples cannot be changed tuple = (1, 2, 'bye') ## this works
如要建立 size-1 元組,單一元素必須在後方加上半形逗號。
tuple = ('hi',) ## size-1 tuple
這是語法中的一個例子,但為了區分元組和在括號中放入運算式的一般情況,必須使用半形逗號。在某些情況下,您可以省略括號,Python 會從您想要的元組中看見。
如果將元組指派給大小相等的變數名稱元組,會指派所有對應的值。如果元組的大小不同,則擲回錯誤。這項功能也適用於清單。
(x, y, z) = (42, 13, "hike") print(z) ## hike (err_string, err_code) = Foo() ## Foo() returns a length-2 tuple
清單理解 (選用)
清單理解是更先進的功能,在某些個案中不需要,但在練習時不需要瞭解,也不需要先瞭解 (亦即可以跳過這個部分)。清單理解是一種撰寫運算式,可以展開為完整清單的運算式。假設我們有 nums [1, 2, 3, 4] 的清單,這是用來計算正方形清單 [1, 4, 9, 16] 的清單:
nums = [1, 2, 3, 4] squares = [ n * n for n in nums ] ## [1, 4, 9, 16]
語法是 [ expr for var in list ]
,for var in list
看起來是一般的迴圈,但不含冒號 (:)。系統會針對每個元素評估左側的 expr,以提供新清單的值。以下是包含字串的範例,每個字串都變更為大寫,並在後面加上「!!!」:
strs = ['hello', 'and', 'goodbye'] shouting = [ s.upper() + '!!!' for s in strs ] ## ['HELLO!!!', 'AND!!!', 'GOODBYE!!!']
您可以針對 for 迴圈右側新增 if 測試,以縮小結果範圍。系統會針對每個元素評估 if 測試,僅包含測試為 true 的元素。
## Select values <= 2 nums = [2, 8, 1, 6] small = [ n for n in nums if n <= 2 ] ## [2, 1] ## Select fruits containing 'a', change to upper case fruits = ['apple', 'cherry', 'banana', 'lemon'] afruits = [ s.upper() for s in fruits if 'a' in s ] ## ['APPLE', 'BANANA']
運動:list1.py
如要練習本節所述的內容,請在使用排序與元組的 list1.py 中,嘗試後續的問題 (位於基本練習中)。