Try   HackMD

Python 串列 (List)

作者:王一哲
第1版:2021年10月21日
第2版:2023年7月11日,修改增加元素、插入元素的文章內容
第3版:2023年8月5日,新增二維串列及進階技巧

串列 (list) 是在 Python 當中儲存大量資料的其中一種格式,以方括號 [] 將資料包起來,我們通常將每一筆資料稱為元素 (element),每一個元素所在的位置為索引值 (index),Python 與 C、C++ 的作法相同,索引值皆從 0 開始。以下是串列的基本性質及操作方式。


建立串列

如果要建立一個變數名稱為 a 的空串列可以這樣做

a = []

串列中可以儲存各種格式的資料,例如數值、字元、字串。如果要在建立的串列時同時設定各個元素的值可以這樣做

a = [0, 1, 2, 3, 4]
b = ['a', 'b', 'c', 'd', 'e']
c = ['a', 'bc', 'def', 'ghij', 'klmno']
d = [0, 'b', 2, 'd', 5]

同一個串列各個元素可以是不同類型的資料,這點與 C、C++ 不一樣。


取出元素

如果要取出串列中的某個元素,可以用索引值處理,例如要取出串列 b 中索引值為 1 的元素寫法為

b[1]

輸出為

'b'

如果要取出串列 b 中索引值為 0 到 4 (不包含4) 的元素寫法有兩種

b[0:4]
b[:4]

輸出為

['a', 'b', 'c', 'd']

如果要在串列 b 中每隔 2 個元素取出索引值為 0 到 4 (不包含4) 的元素,寫法為

b[0:4:2]

輸出為

['a', 'c']

如果要取出串列 b 中索引值為 1 到最後一個元素的寫法為

b[1:]

輸出為

['b', 'c', 'd', 'e']

如果要取出串列 b 的最後一個元素寫法為

b[-1]

輸出為

'e'

如果要取出串列 b 倒數第二個元素的寫法為

b[-2]

輸出為

'd'

如果要將串列 b 倒著輸出,寫法為

b[-1::-1]

輸出為

['e', 'd', 'c', 'b', 'a']

於串列後方增加元素

如果在串列 b 的最後面附加 1 個元素 'f',通常使用的寫法為

b.append('f')

第二種寫法為

b += ['f']

操作後串列 b 變為

['a', 'c', 'd', 'e', 'f']

第二種寫法的好處在於可以一次增加多個元素,例如

b += ['g', 'h', 'i']

操作後串列 b 變為

['a', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

第三種寫法是利用 開箱運算子 (unpacking operator) *,例如

b = [*b, 'g', 'h', 'i']

操作後串列 b 變為

['a', 'c', 'd', 'e', 'f', 'g', 'h', 'i']



於指定的索引值插入元素

最方便的作法是使用 insert。假設串列 b 的內容為

['a', 'b', 'c', 'd', 'e']

如果要在索引值為 2 處插入字串 z,語法為

b.insert(2, 'z')

串列 b 變為

['a', 'b', 'z', 'c', 'd', 'e']



於串列前方插入元素

假設串列 b 的內容為

['a', 'b', 'c', 'd', 'e']

如果要在串列開頭處加入字串 z,串列原來的元素索引值都加1,至少有以下三種寫法。第一種寫法是利用 insert

b.insert(0, 'z')

第二種寫法是利用 +

b = ['z'] + b

第三種寫法是利用 開箱運算子 (unpacking operator) *

b = ['z', *b]

以上三種寫法都會將串列 b 變為

['z', 'a', 'b', 'c', 'd', 'e']



刪除元素

假設串列 b 的內容為

['a', 'b', 'c', 'd', 'e']

如果要取出串列 b 中索引值為 1 的元素,第一種寫法為

del(b[1])

請注意,這個寫法沒有回傳值,只會刪除指定的元素,因此串列 b 變為

['a', 'c', 'd', 'e']

第二種寫法為

e = b.pop(1)

請注意,這個寫法有回傳值,我們是將從串列 b 中刪除的元素回傳給變數 e,因此串列 b 變為

['a', 'c', 'd', 'e']

變數 e 的值為

'b'

pop 預設會回傳串列中的最後一個元素,因此

e = b.pop()

會將串列 b 變為

['a', 'b', 'c', 'd']



複製串列

假設串列 b 的值為

['a', 'b', 'c', 'd', 'e']

如果要狀串列 b 複製的串列 c,有些人會想要用指定的寫法

c = b

但這個寫法是將串列 b 指定給串列 c,如果改變了串列 c 的值,串列 b 會跟著改變,例如

c[0] = 'b'

則串列 b、c 皆變為

['b', 'b', 'c', 'd', 'e']

因此比較好的寫法是

c = b.copy()

這個會將串列 b 的值複製給串列 c,如果再改變這兩個串列的值,則不會影響到另一個串列。


二維串列

如果串列中的元素是一維串列就稱為二維串列,可以先建立一個空的串列,再用 append 加入一維串列;也可以在建立串列時直接指定資料。例如以下的程式碼,a 是先建立空的串列再用 append 加入一維串列,b 是建立串列時直接指定資料,兩都的內容都是 [[0, 1, 2], [3, 4, 5]]。由於二維串列看起來很像數學中的矩陣,通常會沿用矩陣的講法,將 [[0, 1, 2], [3, 4, 5]] 這樣的二維串列稱為 2 列 (row)、3 欄 (column)。

a = []
a.append([0, 1, 2])
a.append([3, 4, 5])
b = [[0, 1, 2], [3, 4, 5]]

但是 Python 的二維串列與 C++ 的陣列 (array) 不同,每一列當中資料數量可以不一樣,例如以下的程式碼。

c = [[0], [1, 2], [3, 4, 5], [6, 7, 8, 9]]

理論上可以産生三維以上的串列,但是這樣不容易想像資料的結構及位置,因此通常只使用一維及二維串列。


進階技巧

産生資料相同、指定長度的一維串列

語法為

串列名稱 = [資料]*長度

例如

a = [0]*5   # a 的內容為 [0, 0, 0, 0, 0]
b = [1]*5   # b 的內容為 [1, 1, 1, 1, 1]
c = [-1]*5  # c 的內容為 [-1, -1, -1, -1, -1]



産生資料為等差數列的一維串列

通常有兩種方法,基本的方法是先産生一個空的串列,再於 for 迴圈中用 append 加入資料,例如以下的程式碼

a = []
for i in range(10):
    a.append(i)

比較偷懶的方法是將 for 迴圈包在同一行當中,例如以下的程式碼

b = [i for i in range(10)]

也可以用 list 將 range 産生的數值轉成串列,例如以下的程式碼

c = list(range(10))

以上三種方法得到的一維串列內容都是 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]。

我們也可以利用 range 的特性,産生內容為 [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 的一維串列,例如以下的程式碼

d = [i for i in range(9, -1, -1)]
e = list(range(9, -1, -1))



印出串列內容,以空格分隔資料

由於許多題目要求印出答案時,要用空格分隔資料,但是最後一筆資料後方不加空格、直接換行,不能直接用 print 印出串列內容。通常有3種方法,基本的方法如下

a = [i for i in range(10)]
for i in range(len(a)):
    if i == len(a)-1:
        print(a[i])
    else:
        print(a[i], end=" ")

比較偷懶的方法是將 if、else 於在 print 同中,例如以下的程式碼

for i in range(len(a)):
    print(a[i], end="\n" if i == len(a)-1 else " ")

更偷懶的方法是利用開箱運算子 (unpacking operator)

print(*a)

以上3個方法輸出皆為

0 1 2 3 4 5 6 7 8 9

同樣的方法也可以用在印出二維串列,例如以下的程式碼

c = [[0], [1, 2], [3, 4, 5], [6, 7, 8, 9]]
for i in range(len(c)):
    for j in range(len(c[i])):
        print(c[i][j], end="\n" if j == len(c[i])-1 else " ")
# 比較偷懶的寫法
for r in c: print(*r)

輸出為

0
1 2
3 4 5
6 7 8 9




tags:Python