我管理世界職業技能競賽之網站技術項目、舉辦本地設計與開發賽事、開課分享技術心得。一個用網頁來表達自己的作家。
Python 使用列表切片 List Slicing 取得列表的範圍數值
曾經,十數年前,我放棄了學習 Python,因為當時我覺得 Python 的語法不好閱讀,用縮排來分開代碼的方式亦不夠穩陣,但有好幾個功能,是令我愛上 Python 的原因,其中一個,就是列表切片(List Slicing)功能,而另外兩個我愛上的,是 BeautifulSoup 套件和 Pandas 套件的使用。
回顧如何在列表中取得一個值
例如有以下列表 names。
names = ['Thomas', 'Steven', 'Jane', 'Tom', 'Susan']
我們可以用 names[0] 取得第一個值,names[-1] 取得最後一個值,names[-2] 取得尾二的值等。
而如果超出了範圍,例如這個 names 列表有五個值,如果 names[5] 則會報錯,指我們提供的數字 Index 超出了範圍。
上述,是在列表中取得一個值的寫法。
列表切片,取得一段範圍的值
而在列表中,我們亦可以取得一個範圍,生成新的列表,我們稱為切片 Slicing,語法和按 Index 取得值差不多,使用 [ 起始 : 終止 ] 的寫法。
例如,有以下列表 sample_list
sample_list = [0,1,2,3,4,5,6,7,8,9] sample_list[0:5]
可以得出頭五個值。其機制是由起始開始數,直至終止為止,不包括終止的那個值。
結果:[0, 1, 2, 3, 4]
而若果開始是 0,則可以省略,例如 [:5] 就是取得頭五個值的列表。
我們亦可以使用負數來取得從尾幾開始數到最後的值,例如:
sample_list[-3:]
會取得最後三個值的列表。
結果:[7, 8, 9]
以上代碼,當終止是留空時,代表直至最後一個值。
全部取值(複製)
那麼,當起始位置及終止位置都留空時,我們會得出整條列表,例如
sample_list[:]
會得出結果:
結果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
那為甚麼是使用 [:]?因為這樣可以取得一個複製的列表,當我們使用切片時,切片取值後得出的是新生成的列表,我們可以通過以下實驗驗證:
實驗一:list_2 直接等於 sample_list
sample_list = [0,1,2,3,4,5,6,7,8,9] list_2 = sample_list list_2[0] = 999 print(sample_list) # 結果:[999, 1, 2, 3, 4, 5, 6, 7, 8, 9]
實驗二:list_3 等於 sample_list[:]
sample_list = [0,1,2,3,4,5,6,7,8,9] list_3 = sample_list[:] list_3[0] = 999 print(sample_list) # 結果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
原因是 list_2 = sample_list 即直接等於 sample_list 所指著的列表位置。而當 list_3 = sample_list[:] 使用切片時,則是生成了一份新的列表,所以修改 list_2 會連同 sample_list 也一起改,但修改 list_3 則不會影響 sample_list。
話說,在 Python 中複製列表還有甚他方法,例如 sample_list.copy()、或 copy.deepcopy(sample_list) 等。可以參考一下這篇 StackOverflow 的解說文。
https://stackoverflow.com/a/2612815/1382695
Skip 跳著跳著取
切片的語法,除了起始位置及終止位置外,亦有第三個值:Skip。即每隔多少取一個值。而預設為 1,即逐個逐個取值。
例如,上述的 sample_list,若我們只想兩個兩個地取值,便可以使用 [::2]。例如:
sample_list = [0,1,2,3,4,5,6,7,8,9] sample_list[::2]
會得出:
[0, 2, 4, 6, 8]
而如果 step 取值 -1,則會變成倒轉取值。例如 [::-1] 。
sample_list = [0,1,2,3,4,5,6,7,8,9] sample_list[::-1] # 結果:[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
切片用途
列表切片有甚麼用途?多了。例如我們從試算表、網絡上等取得數據並處理排序後,想得出頭十筆記錄等,便可以使用 [:10];又或者排序後,最後兩名需要標注出來的,如球隊降班列表、或賽車排位賽淘汰列表等,便可以使用 [-2:] 等;又或者排序後,只保留入圍的名單,例如尾五名的淘汰,其餘入圍,便可以使用 [:-5]。
注意,是 [:-5] 而不是 [-5:],前者是由頭取值至尾五為止(不包括尾五),而後者是由尾五起取值至最尾。
另外,我們讀取一些複雜的試算表,例如以下為澳門統計局的飲食業行業概況 2017 年數據 Excel 表。當中,有按飲食店舖分類的場所數目、員工數目、收益等統計數據。但標題的位置在第 4 行,而結尾亦有幾行的備註是可以省略的。當中可以看到每個場所分類,分別有 2017 年、早一年的數據、及兩年的相差比例,即每三行為之一個場所分類。
當我們使用 Pandas 的 read_excel 時,可以配合 skiprows 跳過頭幾行剩餘的第一行預設為欄標題。然後我們使用列表切片 [5:-9:3],便可以從飲食店舖開始,只讀取 2017 年的分類數據。
import pandas as pd df = pd.read_excel("C_RES_FR_2017_Y.xls", sheet_name="1", skiprows=4) df[5:-9:3]
成功只讀取一年的場所分類數據。
(注:標題欄內容待整理)
總結
我日常工作會用到不同的編程語言,例如 Ruby、JavaScript、PHP、Swift 等每次遇到要從尾讀取列表,或按上述例子的範圍讀取列表時,都會想起 Python 的這個簡便寫法。有了列表切片,可以為我們平常處理數據時大為方便。
— 麥誠 Makzan,2022-01-14。
我是麥誠軒(Makzan),除了正職外,平常我要麼辦本地賽與辦世界賽,要麼任教編程與網站開發的在職培訓。現正轉型將面授培訓內容寫成電子書、網上教材等,至今撰寫了 7 本書, 2 個視頻教學課程。
如果我的文章有價值,請左下角 👍🏻按讚支持,或訂閱贊助我持續創作及分享。
喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。
发布评论…