主要是遇到 map匹配的問題,所以順便回憶一下 erlang 中的對映組 map,在其它語言中被稱作 hash 雜湊或者 dict 字典。
erlang 從 r17 版本開始支援對映組
建立對映組
erlang 中的對映組用結構 #{} 表示,建立乙個對映組可以這樣
% 不管你怎麼排序,最終結果都是按鍵的字典順序排列的
#.% => #
% 也可以建立乙個空的對映組
#{}.
% => #{}
更新對映組
對映組可以更新,所謂的更新是建立乙個新的對映組,因為 erlang 中的變數是不可改變的。
% 現在的我
me = #.
% => #
% 過年啦,又長一歲了,變成嶄新的我啦
newme = me#.
% => #
% 當然也可以直接修改
##.% => #
=> 用於建立或更新乙個對映,如果鍵存在,則更新它,否則就建立乙個新的對映。如果一不小心某個鍵拼寫錯誤,oops.
% 本來想更新 age,結果一不小心拼寫錯誤,建立了乙個新的對映
me#.
% => #.
為了避免這種情況,還有一種更新對映的方法,使用 :=,它只能用來更新對映,而不能建立新的對映,如果鍵不存在,就會丟擲乙個 badarg 異常。
% 不存在 aeg 鍵,丟擲 badarg 異常
me#.
% ** exception error: bad argument ... blabla
% 只能更新已存在的對映
me#.
% => #
兩種操作符的區別
=> 可以用來更新對映或者建立新的對映
:= 只能更新對映,在鍵不存在時會丟擲異常
所以有下面的總結
建立對映組時
只能使用 =>,:= 只能更新對映而無法建立新的對映,而建立對映組時需要建立若干對映
#.% * 1: only association operators '=>' are allowed in map construction
對映組匹配的
左邊只能使用 :=,=> 在鍵不存在時可以建立新的對映,而對映組匹配可以部分匹配 (只匹配左邊擁有的部分) ,所以匹配是沒有意義的
% 部分匹配: 我們只想取出 age,所以我們只關心引數中有沒有 age 這個對映
# = me.
% => #
% age.
% => 19
% 不合法的匹配
# = me.
% * 1: illegal pattern
為了更好的發現錯誤
只在建立對映組或明確需要建立新的對映時使用 =>,而在其它場合均使用 :=
% 這裡是建立對映組,只能使用 =>
new() ->
}}.% 這裡是匹配,只能使用 :=
show(}) ->
io:format("name: ~p, age: ~p~n", [name, age]).
注意上面的更新對映,建立新的對映以及匹配可以同時針對多個對映,這裡只是作為例子而只選擇一對對映。
對映組操作
erlang 中的 maps 模組用於操作對映組
對映組的建立及屬性
% 建立對映組
maps:new().
% => #{}
% 返回所有鍵
maps:keys(me).
% => [age,name]
% 判斷是否存在鍵
maps:is_key(age, me).
% => true
maps:is_key(aeg, me).
% => false
% 按鍵的順序返回所有值
maps:values(me).
% =>[19,"wittyfox"]
% 對映數量
maps:size(me).
% => 2
% 還可以使用 erlang:map_size/1
% 此函式可以用於 guard,maps 模組內部也是使用此函式的
map_size(me).
% => 2
對映的增加、刪除、獲取
% maps:get/2 在鍵不存在時會丟擲異常
maps:get(age, me).
% => 19
% maps:get/3 在鍵不存在時會返回第三個引數的值
maps:get(aeg, me, 20).
% => 20
% 用於更新或建立對映,類似於 =>
% 所謂更新,只是返回更新後的新的對映組,原對映組並不會改變
maps:put(gender, male, me).
% => #
% 用於更新對映,類似於 :=,鍵不存在時會丟擲 badarg 異常
maps:update(age, 20, me).
% => #
% 刪除乙個對映,鍵不存在時相當於什麼都沒做,不會丟擲異常
maps:remove(age, me).
% => #
% 查詢鍵的值,鍵不存在時返回 error
maps:find(age, me).
% =>
maps:find(aeg, me).
% => error
對映組的歸併
% 歸併兩個對映組,注意第二個引數是建立新的對映組,所以只能用 =>
maps:merge(me, #).
% => #
% 相當於
me#.
對映組與列表之間的轉換
% 返回對映元組對的列表
maps:to_list(me).
% => [,]
% 從列表構建對映組
maps:from_list().
% => #{}
maps:from_list([, ]).
% => #
對映組的遍歷
% 對對映組的每對對映執行操作
% x, y 分別為一對對映的鍵和值
maps:map(fun (x, y) -> io:format("~p => ~p~n", [x, y]) end, me).
% age => 19 % 輸出
% name => "wittyfox" % 輸出
% => # % 返回值
% x, y 分別為一對對映的鍵和值,v 為上一次迭代的結果,0 為迭代的初始值
% 這裡簡單的用於每次迭代時值加 1,結果就是對映組的對映數量
maps:fold(fun (x, y, v) -> v + 1 end, 0, me).
% => 2
對映組中對映的選取
返回第乙個引數中指定的鍵的對映組成的對映組
maps:with(, me).
% => #{}
maps:with([age], me).
% => #
% 鍵可以不存在
maps:with([aeg], me).
% => #{}
返回鍵不再第乙個引數的列表中的對映組成的對映組
maps:without(, me).
% => #
maps:without([age], me).
% => #
% 鍵也可以不存在
maps:without([age, neme], me).
% => #
注意值得一提的是 maps 模組中的若干函式,比如 map, fold, with 和 without 都是使用 maps:to_list/1 轉到列表,然後使用 lists 模組的工具處理,然後使用 maps:from_list/1 轉回到對映組的。
Erlang中的對映組Map詳細介紹
主要是遇到 map匹配的問題,所以順便回憶一下 erlang 中的對映組 map,在其它語言中被稱作 hash 雜湊或者 dict 字典。erlang 從 r17 版本開始支援對映組 建立對映組 erlang 中的對映組用結構 表示,建立乙個對映組可以這樣 複製 如下 不管你怎麼排序,最終結果都是按...
Erlang 記錄和對映組
對映組 是鍵 值對的關聯性集合。記錄 是元組的另一種表示形式,它的儲存與效能特性和元組一樣。記錄的語法形式 record name,說明 name 為記錄的名稱,key1,key2為記錄的各個字段必須為原子。記錄的定義可以儲存在erlang源 檔案裡,也可以由擴充套件名為.hrl的檔案儲存,然後包含...
Erlang(6) 記錄和對映組
記錄record 是元組的另一種形式 record name,記錄比較像c 的結構和類。hrl有點想c 的.h檔案 test.hrl record todo,定義乙個叫做todo的記錄。指定了預設值。31 rr test.hrl todo 在shell裡面讀入記錄的定義。rr 是read recor...