Erlang Thursday – dict:merge/3

今天的Erlang Thursday讲的是 dict:merge/3.

dict:merge/3 有三个入参,第一个入参是一个合并函数,它在发生键冲突的时候被调用,第二和第三个入参都是字典。

合并函数用键作为第一个入参,第一个字典对应的值作为第二个入参,第二个字典来对于的值作为第三个入参。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
dict:merge(fun (_Key, Value1, Value2) -> [Value1, Value2] end,
dict:from_list([{a, 1}, {b, 2}, {x, 5}]),
dict:from_list([{x, 7}, {y, 8}, {z, 10}])).
% {dict,5,16,16,8,80,48,
% {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
% {{[],
% [[a|1]],
% [[b|2]],
% [],[],[],[],[],
% [[x,5,7]],
% [[y|8]],
% [[z|10]],
% [],[],[],[],[]}}}
dict:merge(fun (_Key, Value1, Value2) -> Value1 * Value2 end,
dict:from_list([{a, 1}, {b, 2}, {x, 5}]),
dict:from_list([{x, 7}, {y, 8}, {z, 10}])).
% {dict,5,16,16,8,80,48,
% {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
% {{[],
% [[a|1]],
% [[b|2]],
% [],[],[],[],[],
% [[x|35]],
% [[y|8]],
% [[z|10]],
% [],[],[],[],[]}}}

传给dict:merge/3的合并函数仅在发生冲突的时候才被调用。如下代码例子,合并函数体里有一个exit的调用,只要合并函数备调用就将导致进程的结束。(译者注:此处的代码并没有触发合并函数的调用,因为两个字典没有相同的键)

1
2
3
4
5
6
7
8
9
10
11
12
13
dict:merge(fun (_Key, _Value1, _Value2) -> exit(merge_happened) end,
dict:from_list([{a, 1}, {b, 2}]),
dict:from_list([{x, 7}, {y, 8}, {z, 10}])).
% {dict,5,16,16,8,80,48,
% {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
% {{[],
% [[a|1]],
% [[b|2]],
% [],[],[],[],[],
% [[x|7]],
% [[y|8]],
% [[z|10]],
% [],[],[],[],[]}}}

如果你想让合并函数将第二个字典覆盖第一个字典,那么合并函数在出现键冲突的时候只需要返回第二个字典里的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
dict:merge(fun (_Key, _Value1, Value2) -> Value2 end,
dict:from_list([{a, 1}, {b, 2}, {x, 5}]),
dict:from_list([{x, 7}, {y, 8}, {z, 10}])).
% {dict,5,16,16,8,80,48,
% {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
% {{[],
% [[a|1]],
% [[b|2]],
% [],[],[],[],[],
% [[x|7]],
% [[y|8]],
% [[z|10]],
% [],[],[],[],[]}}}

如果你想保持第一个字典里的所有键和值,仅仅是将那些不在第一个字典里而在第二个字典里的键和值加进来,合并函数只需要返回第一个字典的相关值。

1
2
3
4
5
6
7
8
9
10
11
12
13
dict:merge(fun (_Key, Value1, _Value2) -> Value1 end,
dict:from_list([{a, 1}, {b, 2}, {x, 5}]),
dict:from_list([{x, 7}, {y, 8}, {z, 10}])).
% {dict,5,16,16,8,80,48,
% {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
% {{[],
% [[a|1]],
% [[b|2]],
% [],[],[],[],[],
% [[x|5]],
% [[y|8]],
% [[z|10]],
% [],[],[],[],[]}}}

另外,大家可以关注Erlang 17.0中引入的新数据类型Maps。

原文链接: https://www.proctor-it.com/erlang-thursday-dict-merge-3/