iT邦幫忙

2025 iThome 鐵人賽

DAY 4
0

Map (映射)

在 Elixir 裡也有類似其他語言的字典或雜湊表

%{
  "name" => "Jack",
  "age" => 33
}

immutable (不可變性)

當需要增減或是修改 map 的項目時,
每次更動都會產生一個新的 map,
Elixir 在這部分有基於這個特性的記憶體優化 (結構共享),
但我們並不需要擔心這一部分,只要記得每次改動都是新的 map 即可

增減項目

常用操作 map 的函式都在 Map 模組

# 定義 map
%{} # 可以建立空 map

# 任何值都可以當 key 與 value
%{3 => 4.4}
%{%{3 => 4} => 5}

# 常用 Map.get 取值
Map.get(%{}, "a")
#=> nil
Map.get(%{"a" => 1}, "a")
#=> 1

# 也可以用中括號取值
%{"a" => 1}["a"] #=> 1

# 可以用 Map.put 回傳一個加入新 key value 的 map
# 原本的不會改變

a = %{"name" => "Ann"}
b = Map.put(a, "age", 33)
b #=> %{"age" => 33, "name" => "Ann"} # 新的
a #=> %{"name" => "Ann"} # 舊的

atom 為 key 的簡寫

在所有的 key 都是 atom 的時候 (非常常用)
可以使用 : 簡寫

%{:name => "Jack"}
# 等同於
%{name: "jack"}

在這個情況的 map 可以用 . 來取值

profile = %{name: "Jack", age: 23}
profile.name #=> "Jack"
profile.age #=> 23

# 不過這個方法不能取沒有的 key
%{d: 3}.f
(KeyError) key :f not found in: %{d: 3}

小心不能用從物件導向方式

這樣寫不行

profile = %{name: "Ken", age: 33}

profile[:age] = 55 # error

對於 Elixir 來說 profile[:age] = 55 這一段是 pattern matching
等同於 33 = 55 導致程式報錯

應改成以下幾種寫法之一

profile = %{name: "Ken", age: 33}

profile = Map.put(profile, :age, 33) # 不管 profile 有沒有 age 都直接取代
profile = Map.replace(profile, :age, 33) # 只要 profile 有 age 就取代

Map 的 pattern matching

Map 在 pattern matching 的時候有點像篩子

%{"⭐️" => n} = %{"⭐️" => 3, "🌛" => 3, "🌞" => 4}
n #=> 3

https://ithelp.ithome.com.tw/upload/images/20250917/20141054tjfLtzqc7E.png

也可以一次拿多個

profile = %{name: "Ann", age: 32, mail: "ann@ma.il", mood: "Good"}

%{name: name, mood: mood} = profile
name #=> "Ann"
mood #=> "Good"

既然是 pattern matching 當然要在 case 用用看

case profile do
  %{name: "Jack"} -> "只有 name 是 Jack 的會匹配到這行"
  %{age: age} when age < 9 -> "匹配出 age 再判斷"
  %{name: n, mood: m} when n == m -> "name 跟 mood 的值一樣才會匹配"
  %{name: x, mood: x} -> "上一行其實可以寫這樣,直接匹配兩個欄位為 x"
  %{} -> "只要 profile 是 map 就會匹配"
  _ -> "上面的都沒匹配才會到這"
end

Tuple (元組)

Tuple 是用來用來表示具有固定結構的小型資料組合
在 Elixir 中常用在

  • 函式回覆 {:ok, data}, {:error, reason}
  • 座標、色彩RGB類的固定短資料
{:ok, 33}
{x, y} = {22.3, -73}
{r, g, b} = {255, 255, 255}

常用的函式回覆情景

在 Elixir 社群,套件都有共識的使用 {:ok, “回傳值"} 來代表沒有異常的回傳結果
尤其是 http 要求的套件,檔案的讀取等有機會有例外的行為,就會使用
{:ok, 資料}:error{:error, 原因} 這種模式來讓使用者方便處理
我們可以用 pattern matching 來處理這些例外

舉剛剛使用的 Map 模組的函式中的 Map.fetch

profile = %{name: "Tim"}

case Map.fetch(profile) do
  {:ok, name} -> name
  :error -> "沒有 name"
end

上一篇
過一遍常用的複合型態 - List
系列文
通勤看手機就可讀懂的 Elixir 語言入門教學4
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言