Makzan
Makzan

我管理世界職業技能競賽之網站技術項目、舉辦本地設計與開發賽事、開課分享技術心得。一個用網頁來表達自己的作家。

Python 使用列表切片 List Slicing 取得列表的範圍數值

曾經,十數年前,我放棄了學習 Python,因為當時我覺得 Python 的語法不好閱讀,用縮排來分開代碼的方式亦不夠穩陣,但有好幾個功能,是令我愛上 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 年、早一年的數據、及兩年的相差比例,即每三行為之一個場所分類。

澳門統計局的 2017 飲食業數據表
澳門統計局的 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]

成功只讀取一年的場所分類數據。

(注:標題欄內容待整理)

使用 Pandas 讀取 Excel 後,再使用切片抽取中間需要的數據列

總結

我日常工作會用到不同的編程語言,例如 Ruby、JavaScript、PHP、Swift 等每次遇到要從尾讀取列表,或按上述例子的範圍讀取列表時,都會想起 Python 的這個簡便寫法。有了列表切片,可以為我們平常處理數據時大為方便。

— 麥誠 Makzan,2022-01-14。


我是麥誠軒(Makzan),除了正職外,平常我要麼辦本地賽與辦世界賽,要麼任教編程與網站開發的在職培訓。現正轉型將面授培訓內容寫成電子書、網上教材等,至今撰寫了 7 本書, 2 個視頻教學課程。

如果我的文章有價值,請左下角 👍🏻按讚支持,或訂閱贊助我持續創作及分享。

麥誠 Makzan


CC BY-NC-ND 2.0 版权声明

喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。

加载中…
加载中…

发布评论