iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 5
1
Modern Web

用Elixir學習後端煉金術系列 第 5

Day 5 |> 集合資料型態 ( Collection ) - List (串列)

List (串列)


在elixir中,List串列是資料結構中的single-linked-list的實作,他長得像這樣:
[1, "haha", :test, 34, 3]

雖然跟PHP還有JS的Array很像,但他的本質是連結串列,所以他裡面的內容是分散的記憶體,並藉由指標的方式連結起來,因此假如你現在想抓到這個串列的第3項,你必須先從第0項,找到第1項,第2項,才能找到第3項,得到他的內容是34。如果你想找到這個陣列的第n項,就必須花費O(n)的複雜度。

因此List的功能也是比較明確的,他適合用來遍歷,對於依序處理或是依序讀取List中的資料,Elixir提共了相對應的函式模組,並且可以得到好的效能。

  • 基本運算
  1. -- (取差集,可以注意到範例中的2只被扣掉一個)
iex(1)> [1, 2, 6, 3, 2] -- [1, 3, 2]
[6, 2]
  1. ++ (串列串接)
iex(1)> [1, 2, 6, 3, 2] ++ [1, 3, 2]
[1, 2, 6, 3, 2, 1, 3, 2]

且由於串列的性質,下列第一種情況會比第二種來得快。

iex(1)> [1] ++ [1, 3, 2, 4, 7, 8]
[1, 1, 3, 2, 4, 7, 8]
iex(2)> [1, 3, 2, 4, 7, 8] ++ [1]
[1, 3, 2, 4, 7, 8, 1]
  1. in
iex(1)> 6 in [1, 2, 6, 3, 2]
true
  1. length (計算List長度需花費線性時間)
iex(1)> length([1, 2, 6, 3, 2])
5

Keyword List (關鍵字串列)
有著簡單的鍵值的串列是常有可能被需要的,所以elixir提供一種資料型態(其實算是種語法糖):

[name: "jack", age: 18, cell: "0911111111"]

elixir在編譯時會將上述語法轉化成:

[{:name, "jack"}, {:age, 18}, {:cell, "0911111111"}]

也就是List包裝Tuples。

然後當然,因為Keyword List的本質上就是List而已,所以下面的語法也是被允許的。
[name: "jack", age: 18, cell: "0911111111", "hahah", 123]
會被編譯成
[{:name, "jack"}, {:age, 18}, {:cell, "0911111111"}, "hahah", 123]


賦值

在elixir中,可以使用下面這種類似語法,達到類似JS中的解構賦值的效果,這都是得益於elixir的pattern matching,在之後的章節會提到。

iex(1)> [a, b, c] = [1, 2, 3]
[1, 2, 3]
iex(2)> a
1
iex(3)> b
2
iex(4)> c
3
iex(1)> [head | tail] = [1, 2, 3]
[1, 2, 3]
iex(2)> head
1
iex(3)> tail
[2, 3]

事實上,List的表示法也算是一種語法糖,其實他真正的樣子是這樣的:

[1, 2, 3] 其實長這樣 => [1 | [2 | [3 | []]]]

而當你在iex輸入時也可以看到相同的結果:

iex(1)> [1 | [2 | [3 | []]]]
[1, 2, 3]

所以看到這邊,就可以大概了解[head | tail] = [1, 2, 3]可以做到解構賦值的原因了吧。


相關函式
如一些基本的新增刪除,都可以在文檔中找到,因此這邊就不寫了,只找幾個實務上最可能會有機會用到的列出來。
List官方文檔([https://hexdocs.pm/elixir/List.html])

  1. List.flatten (可以將串列中的串列給打平,也就是將多層的List壓成一層。)
List.flatten([1, [[2], 3]])
[1, 2, 3]
  1. Enum.map
    如同JS Array 的 map
Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]
  1. Enum.each
    如同JS Array 的 forEach
Enum.each(["some", "example"], fn x -> IO.puts(x) end)
"some"
"example"
#=> :ok
  1. Enum.filter
    如同JS Array 的 filter
Enum.filter([1, 2, 3], fn x -> rem(x, 2) == 0 end)
[2]
  1. Enum.reduce
    類似於JS Array 的 reduce
Enum.reduce([1, 2, 3], 0, fn x, acc -> x + acc end)
6

上一篇
Day 4 |> 集合資料型態 ( Collection ) - Tuple (元組)
下一篇
Day 6 |> 集合資料型態 ( Collection ) - Map (映射)
系列文
用Elixir學習後端煉金術30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言