iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0
  • 建立(create)串列
  • 訪問(accessing)串列
  • 開箱(unpacking)串列
  • 片取(slicing)串列元素
  • 修改(modifying)串列
  • 確認(checking)串列是否有某一元素
  • 添加(adding)元素到現有串列中
  • 插入(inserting)元素到現有串列中
  • 從現有串列中移除(removing)元素
  • 清空(clearing)串列
  • 複製(copying)串列
  • 結合(joining)串列
  • 計算(counting)串列中某一元素的數目
  • 找出(finding)某一元素的索引
  • 反轉(reversing)串列
  • 排序(sorting)串列元素
  • 補充:keyword-only和positional-only

這篇文章是閱讀Asabeneh的30 Days Of Python: Day 5 - Lists後的學習筆記與心得。


Python中串列(List)的定義類似JavaScript (以下簡稱JS)的陣列(array)。

建立(create)串列

建立一個空串列有兩種方式:

  • 使用內建函式,類似JS的new Array()
empty_list = list()
  • 使用方框,跟JS相同
empty_list = []

如果建立有值的串列也跟JS一樣:

greetings = ["Hello", "你好", "こんにちは"]

訪問(accessing)串列

要取值的話還是跟JS一樣(not really):

greetings = ["Hello", "你好", "こんにちは"]
first_greeting = greetings[0]
print(first_greeting) # 'Hello'
print(greetings[1]) # '你好'

跟JS不太一樣的是可以接受負值,變成取倒數過來位置的值:

greetings = ["Hello", "你好", "こんにちは"]
last_greeting = greetings[-1]
print(last_greeting) # 'こんにちは'
print(greetings[-3]) # 'Hello'

開箱(unpacking)串列

可以想成是JS的解構賦值(destructuring assignment),不同的是,在Python必須連元素(items)個數都相符,不然會報錯:

colors = ["red", "green", "blue", "yellow", "orange", "purple"]
apple, leaf, sky = colors # ValueError

在這種情況下,可以利用*加變數名稱來收集剩餘的值成另一個串列,像是JS的展開運算子(spread syntax)

colors = ["red", "green", "blue", "yellow", "orange", "purple"]
apple, leaf, sky, *mix = colors
print(apple) # 'red'
print(mix) # ['yello', 'orange', 'purple']

片取(slicing)串列元素

如同day 4中片取字串中字元提過:

colors = ["red", "green", "blue", "yellow", "orange", "purple"]

rgb = [0:3]
mixture = [-3:]

print(rgb) # ['red', 'green', 'blue']
print(mixture) # ['yellow', 'orange', 'purple']

修改(modifying)串列

跟JS陣列一樣,串列是可改動的(mutable):

colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors[2] = "cyan" # change "blue" to "cyan"
print(colors) # ['red', 'green', 'cyan', 'yellow', 'orange', 'purple']

確認(checking)串列是否有某一元素

可以使用in這個運算子:

colors = ["red", "green", "blue", "yellow", "orange", "purple"]
has_yellow = "yellow" in colors
has_pink = "pink" in colors
print(has_yellow) # True
print(has_pink) # False

添加(adding)元素到現有串列中

使用append(item)這個方法,類似於JS的push()

colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors.append("pink")
print(colors) # ['red', 'green', 'blue', 'yellow', 'orange', 'purple', 'pink']

插入(insertng)元素到現有串列中

使用insert(index, item)這個方法,類似JS的splice(index, 0, item)index也可以接受負值:

colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors.insert(3, "teal")
colors.insert(-1, "pink")
print(colors) # ['red', 'green', 'blue', 'teal', 'yellow', 'orange', 'pink', 'purple']

從現有串列中移除(removing)元素

使用remove(item)方法

如果有多個相符合的元素,會移除第一個,沒有符合的元素的話產生ValueError

# there are two "red" in the start and the end, respectively
colors = ["red", "green", "blue", "yellow", "orange", "purple", "red"]
colors.remove("red")
print(colors) # ['green', 'blue', 'teal', 'pink', 'yellow', 'orange', 'purple', 'red']

colors.remove("pink") # ValueError

使用pop([index = -1])方法

如果沒有指定index值的話(預設是-1),會跟JS的Array.prototype.pop()一樣,會移除串列中最後一個元素。不然的話,會移除該index值位置的元素;回傳值為移除的元素值:

colors = ["red", "green", "blue", "teal", "pink", "yellow", "orange", "purple"]

colors.pop() # 'purple'
print(colors) # ['red', 'green', 'blue', 'teal', 'pink', 'yellow', 'orange']

colors.pop(3) # 'teal'
print(colors) # ['red', 'green', 'blue', 'pink', 'yellow', 'orange']

使用del keyword

可以移除指定位置的值,或是移除整個串列:

colors = ["red", "green", "blue", "yellow", "orange", "purple"]

del colors[0]
print(colors) # ["green", "blue", "yellow", "orange", "purple"]

del colors[1]
print(colors) # ["green", "yellow", "orange", "purple"]

del colors[1:3]
print(colors) # ["green", "purple"]

# delete the list
del colors
print(colors) # NameError

類似JS的delete,但index會更新,在JS中會造成,同樣的操作會把原本該位置的值變成undefined

const test = ["foo", "bar"];
delete test[0]; // returns true
console.log(test) // [empty, "bar"]

清空(clearing)串列

使用clear()方法:

colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors.clear()
print(colors) # []

複製(copying)串列

使用copy()方法,可以複製現有串列的值到新串列中,類似JS中newArray = currentArray.slice()的操作:

colors = ["red", "green", "blue", "yellow", "orange", "purple"]
rgb = colors.copy()
del rgb[3:6]
print(rgb) # ["red", "green", "blue"]
print(colors) # ["red", "green", "blue", "yellow", "orange", "purple"]

如果是使用指派的方式rgb = colors,則會讓rgb指向colors的記憶體位址(copy by ref),對rgb的改動會反映到colors上,反之亦然,這點在JS上相同。

結合(joining)串列

透過+(plus operator)

peripherals = ["keyboard", "mouse"]
computers = ["laptop", "desktop"]
bundles = peripherals + computers
print(bundles) # ['keyboard', 'mouse', 'laptop', 'desktop']

透過extend(iterable)方法

dogs = ["golden retriever", "labrador"]
animals = ["cat", "pig"]
animals.extend(dogs)
print(animals) # ['cat', 'pig', 'golden retriever', 'labrador']

計算(counting)串列中某一元素的數目

使用count(item)方法,回傳item參數在串列中出現的次數:

ages = [18, 20, 25, 28, 32, 18, 21, 25]
print(ages.count(18)) # 2

找出(finding)某一元素的索引

使用index(item)方法,回傳第一個找到的元素,沒有符合的元素的話產生ValueError

ages = [18, 20, 25, 28, 32, 18, 21, 25]
print(ages.index(25)) # 2
print(ages.index(24)) # ValueError

反轉(reversing)串列

使用reverse()方法,跟JS的Array.prototype.reverse()一樣:

colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors.reverse()
print(colors) # ['purple', 'orange', 'yellow', 'blue', 'green', 'red']

排序(sorting)串列元素

使用sort(*, key=None, reverse=False)方法,如果有給reverse=True參數的話,會變成降冪(descending order)排列;如果有給key=fn的話會在排序時對每個元素執行fn再以執行後的元素值排序,但不會改變原有的元素值:

ages = [18, 20, 25, 28, 32, 18, 21, 25]
ages.sort()
print(ages) # [18, 18, 20, 21, 25, 25, 28, 32]

ages.sort(reverse=True)
print(ages) # [32, 28, 25, 25, 21, 20, 18, 18]

colors = ["red", "green", "blue", "Yellow", "orange", "purple"]
colors.sort()
print(colors) # ['Yellow', 'blue', 'green', 'orange', 'purple', 'red']
# sorting in lowercase char order
colors.sort(key=str.lower)
print(colors) # ['blue', 'green', 'orange', 'purple', 'red', 'Yellow']

使用sorted(iterable, /, *, key=None, reverse=False)函式,會回傳排序後的串列,不會修改原始串列:

ages = [18, 20, 25, 28, 32, 18, 21, 25]

sorted_ages = sorted(ages)
print(sorted_ages) # [18, 18, 20, 21, 25, 25, 28, 32]
print(ages) # [18, 20, 25, 28, 32, 18, 21, 25]

sorted_ages_desc = sorted(ages, reverse=True)
print(sorted_ages_desc) # [32, 28, 25, 25, 21, 20, 18, 18]

colors = ["red", "green", "blue", "Yellow", "orange", "purple"]
sorted_colors = sorted(colors)
print(sorted_colors) # ['Yellow', 'blue', 'green', 'orange', 'purple', 'red']
print(colors) # ['red', 'green', 'blue', 'Yellow', 'orange', 'purple']

sorted_colors_by_lowercase = sorted(colors, key=str.lower)
print(sorted_colors_by_lowercase) # ['blue', 'green', 'orange', 'purple', 'red', 'Yellow']

JS及Python中sort()有所不同

參考James Yoo的Sort Function in JavaScript and Python

  • JS是依字典序(Lexicographical order),資料都會先轉成字串再排序。
  • Python則是看資料類型,如果是數字會用數值序(Numerical order),字串則是字典序。

文章中舉了很清楚例子:

const arr = [-1, -10, -2, 3, 4, 5];
arr.sort();
console.log(arr); // [-1, -10, -2, 3, 4, 5]
arr = [-1, -10, -2, 3, 4, 5];
arr.sort()
print(arr) // [-10, -2, -1, 3, 4, 5]

補充:keyword-only和positional-only

官方文件#list.sort寫的參數說明中有個*符號,這是指keyword-only,簡單來說,它會鎖住這個函式(方法)呼叫時要使用的引數名稱,所以sort(True)不行。

更多例子可以參考:Forced naming of parameters in Python | stackoverflow]

另外Python 3.8以上,可以在參數中加入/符號標示positional-only,相關例子可以參考:What is the meaning of a forward slash "/" in a Python method signature, as shown by help(foo) | stackoverflow


上一篇
【Day 4】字串
下一篇
【Day 6】元組
系列文
從前端角度看30天學Python30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言