erlang 映射的创建和更新、maps模块的处理

  • 分类: Erlang
  • 发表日期:2022-01-06 14:32:00
  • 最后修改:2022-01-17 15:19:00

映射 (Map)

映射组是键--值对的关联性集合。键可以是任意的Erlang数据类型。 键和值可以是任何有效的Erlang数据类型 注:map 要更新到最新的erl版本才能运行(R17版本的erlang 才添加map,所以致少要升到R17的版本)

%%Erlang R15B03  版本报错
➜  Cellar erl
Erlang R15B03 (erts-5.9.3.1) [source] [64-bit] [smp:8:8] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.3.1  (abort with ^G)
1> #{name =>"yzf" ,age=>26}. 
* 1: syntax error before: '{'
1>
%%Erlang/OTP 19 版本可以执行成功
[root@iz7mrdaho3jf9lz otp_src_19.1]# erl
Erlang/OTP 19 [erts-8.1] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V8.1  (abort with ^G)
1> #{age => 26,name => "yzf"}.
#{age => 26,name => "yzf"}

创建映射组

Erlang 中的映射组用结构 #{} 表示

1> #{name => "youname", age=> 26}.
#{age => 26,name => "youname"}
%输出
2> #{}.
#{}
3>

更新映射组

% => 用于创建或更新一个映射
13> Me = #{name =>"zyf",age =>26}.
#{age => 26,name => "zyf"}
14> NewMe = Me#{age => 20}.
#{age => 20,name => "zyf"}
15> Me.
#{age => 26,name => "zyf"}
16> 
16> #{name =>"zyf",age =>26}#{age =>27}.
#{age => 27,name => "zyf"}
17>
% 使用 :=,它只能用来更新映射,而不能创建新的映射,如果键不存在,就会抛出一个 badarg 异常
1> Me = #{name =>"zyf",age =>26}.
#{age => 26,name => "zyf"}
2> Me#{age := 27}.               
#{age => 27,name => "zyf"}
3> Me#{aeg := 27}.
** exception error: {badkey,aeg}
     in function  maps:update/3
        called as maps:update(aeg,27,#{age => 26,name => "zyf"})
     in call from erl_eval:'-expr/5-fun-0-'/2 (erl_eval.erl, line 255)
     in call from lists:foldl/3 (lists.erl, line 1263)
4>

将Map里的参数匹配出来

%部分匹配:
%只取出一个参数的映射
1> Me = #{age=> 19,name=>"zyfa"}.
#{age => 19,name => "zyfa"}
2> #{age := NewAge}=Me.
%重新匹配
#{age => 19,name => "zyfa"}
3> NewAge .
19
4> 
4> #{age => NewAge2}=Me.
* 2: illegal pattern
%用=>符号去匹配会报错
5>


maps 模块

Erlang 中的 maps 模块用于操作映射组

映射组的创建及属性

%创建
6> maps:new().
#{}
%新建一个Me的映射
7> Me =#{age=>19,name=>"zyf"}.
#{age => 19,name => "zyf"}

%查询映射的所有键
8> maps:keys(Me).
[age,name]
9> 

%判断是否存在键
%存在时
10> maps:is_key(age,Me).
true
%不存在时
11> maps:is_key(age111,Me).
false

%查询出Me里面的所有值
12> maps:values(Me).
[19,"zyf"]

%查询映射里面的数量
13> maps:size(Me).
2
% erlang:map_size/1 此函数可以用于 Guard,maps 模块内部也是使用此函数的
14> map_size(Me).
2
15>

映射的增加、删除、获取

% 获取映射里面的 age key 的值,找不到key时会报错
16> maps:get(age,Me).
19

% 查不到age123这个key的值,会报异常提示
17> maps:get(age123,Me).
** exception error: {badkey,age123}
     in function  maps:get/2
        called as maps:get(age123,#{age => 19,name => "zyf"})
18> 

% maps:get/3 在键不存在时会返回第三个参数的值
18> maps:get(age123,Me,18).

% 添加参数到映射里面,原映射组并不会改变
19> maps:put(gender,male,Me).
#{age => 19,gender => male,name => "zyf"}
20> Me.
#{age => 19,name => "zyf"}

% 用于更新映射,类似于 :=,键不存在时会抛出 badarg 异常
21> 
21> maps:update(age,20,Me).
#{age => 20,name => "zyf"}
22> maps:update(age321,20,Me).
** exception error: {badkey,age321}
     in function  maps:update/3
        called as maps:update(age321,20,#{age => 19,name => "zyf"})
23> 

% 删除一个映射,键不存在时相当于什么都没做,不会抛出异常
23> maps:remove(age,Me).
#{name => "zyf"}
24> 

% 查找键的值,键不存在时返回 error
24> maps:find(age,Me).
{ok,19}
25> Me.
#{age => 19,name => "zyf"}
26> maps:find(age3,Me).
error
27>

映射组的归并

% 新建一个Me映射
1> Me=#{age=> 10,name=>"zyfaa"}.
#{age => 10,name => "zyfaa"}

%新建一个Me1映射
2> Me2=#{height=>173}. 
#{height => 173}

%将Me、Me2合并 height键会合并到新的映射里面
3> maps:merge(Me,Me2).
#{age => 10,height => 173,name => "zyfaa"}

%新建一个Me3映射,age为39
4> Me3=#{age=>39}.
#{age => 39}

%将Me、Me3合并 age会更新到最新的值
5> maps:merge(Me,Me3).
#{age => 39,name => "zyfaa"}

映射组与列表之间的转换

5> Me=#{age=> 10,name=>"zyfaa"}.
#{age => 10,name => "zyfaa"}

% 返回映射对应的列表
6> maps:to_list(Me).
[{age,10},{name,"zyfaa"}]

%从列表构建一个空的映射组
7> maps:from_list([]).
#{}
8> 

%从列表构建一个新的映射组
9> maps:from_list([{name,"zfsfd"},{age,33}]).      
#{age => 33,name => "zfsfd"}
10> Me21 = maps:from_list([{name,"zfsfd"},{age,33}]).
#{age => 33,name => "zfsfd"}
11>

映射组的遍历

% 对映射组的每对映射执行操作
% X, Y 分别为一对映射的键和值
11> Me21 = maps:from_list([{name,"zfsfd"},{age,33}]).
#{age => 33,name => "zfsfd"}
12> maps:map(fun (X, Y) -> io:format("~p => ~p~n",[X, Y]) end,Me21).
age => 33
name => "zfsfd"
#{age => ok,name => ok}
13> 
% X, Y 分别为一对映射的键和值,V 为上一次迭代的结果,0 为迭代的初始值
% 这里简单的用于每次迭代时值加 1,结果就是映射组的映射数量
13> maps:fold(fun(X,Y,V) ->V + 1 end,0,Me).
2

映射组中映射的选取

1、返回第一个参数中指定的键的映射组成的映射组

14> maps:with([],Me).
#{}
15> maps:with([name],Me).
#{name => "zyfaa"}
16> maps:with([age],Me). 
#{age => 10}
17> 
17> maps:with([age22],Me).
#{}

2、返回键不再第一个参数的列表中的映射组成的映射组

18> maps:without([],Me).
#{age => 10,name => "zyfaa"}
19> 
19> maps:without([age],Me).
#{name => "zyfaa"}
20> maps:without([age,name],Me).
#{}
% 键也可以不存在
21> maps:without([age,name234],Me).
#{name => "zyfaa"}
22>

注意

值得一提的是 maps 模块中的若干函数,比如 map, fold, with 和 without 都是使用 maps:to_list/1 转到列表,然后使用 lists 模块的工具处理,然后使用 maps:from_list/1 转回到映射组的。

 

作者:zhang_yongfeng
链接:https://www.jianshu.com/p/89bacbbc72f3

 

post
2021年11月2日 11:26
post
2021年11月4日 18:46
post
2021年11月24日 16:09
post
2022年1月6日 17:26

0 评论

大哥整点话呗~