`
lzs2014193
  • 浏览: 25583 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Erlang中的映射组Map详细介绍

 
阅读更多

原文地址:http://www.jb51.net/article/61023.htm

这篇文章主要介绍了Erlang中的映射组Map详细介绍,本文讲解了创建映射组、更新映射组、两种操作符的区别、映射的增加、删除、获取等内容,需要的朋友可以参考下。
主要是遇到 Map匹配的问题,所以顺便回忆一下 Erlang 中的映射组 Map,在其它语言中被称作 Hash 哈希或者 Dict 字典。Erlang 从 R17 版本开始支持映射组。

创建映射组

Erlang 中的映射组用结构 #{} 表示,创建一个映射组可以这样

复制代码代码如下:

% 不管你怎么排序,最终结果都是按键的字典顺序排列的
#{ name => "wittyfox", age => 19 }.
% => #{age => 20,name => "wittyfox"}

 

% 也可以创建一个空的映射组
#{}.
% => #{}

 

更新映射组

映射组可以更新,所谓的更新是创建一个新的映射组,因为 Erlang 中的变量是不可改变的。

复制代码代码如下:

% 现在的我
Me = #{ name => "wittyfox", age => 19 }.
% => #{age => 19,name => "wittyfox"}

 

% 过年啦,又长一岁了,变成崭新的我啦
NewMe = Me#{ age => 20 }.
% => #{age => 20,name => "wittyfox"}

% 当然也可以直接修改
#{ name => "wittyfox", age => 19 }#{ age => 20 }.
% => #{age => 20,name => "wittyfox"}

 

=> 用于创建或更新一个映射,如果键存在,则更新它,否则就创建一个新的映射。如果一不小心某个键拼写错误,Oops.

复制代码代码如下:

% 本来想更新 age,结果一不小心拼写错误,创建了一个新的映射
Me#{ aeg => 20 }.
% => #{aeg => 20,age => 19,name => "wittyfox"}.

为了避免这种情况,还有一种更新映射的方法,使用 :=,它只能用来更新映射,而不能创建新的映射,如果键不存在,就会抛出一个 badarg 异常。
复制代码代码如下:

% 不存在 aeg 键,抛出 badarg 异常
Me#{ aeg := 20 }.
% ** exception error: bad argument ... blabla

 

% 只能更新已存在的映射
Me#{ age := 20 }.
% => #{age => 20,name => "wittyfox"}

 

两种操作符的区别

1.=> 可以用来更新映射或者创建新的映射
2.:= 只能更新映射,在键不存在时会抛出异常
所以有下面的总结

创建映射组时

只能使用 =>,:= 只能更新映射而无法创建新的映射,而创建映射组时需要创建若干映射

复制代码代码如下:

#{ name := "wittyfox", age := 19 }.
% * 1: only association operators '=>' are allowed in map construction

映射组匹配的

 

左边只能使用 :=,=> 在键不存在时可以创建新的映射,而映射组匹配可以部分匹配 (只匹配左边拥有的部分) ,所以匹配是没有意义的

复制代码代码如下:

% 部分匹配: 我们只想取出 age,所以我们只关心参数中有没有 age 这个映射
#{ age := Age } = Me.
% => #{age => 19,name => "wittyfox"}

 

% Age.
% => 19

% 不合法的匹配
#{ age => Age } = Me.
% * 1: illegal pattern


为了更好的发现错误

 

只在创建映射组或明确需要创建新的映射时使用 =>,而在其它场合均使用 :=

复制代码代码如下:

 % 这里是创建映射组,只能使用 =>
 new() ->
     {ok, {?MODULE, #{name => "wittyfox", age => 19}}}.

 

 % 这里是匹配,只能使用 :=
 show({?MODULE, #{name := Name, age := Age}}) ->
     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).
% => #{age => 19,gender => male,name => "wittyfox"}

% 用于更新映射,类似于 :=,键不存在时会抛出 badarg 异常
maps:update(age, 20, Me).
% => #{age => 20,name => "wittyfox"}

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

% 查找键的值,键不存在时返回 error
maps:find(age, Me).
% => {ok, 19}

maps:find(aeg, Me).
% => error

 

映射组的归并

复制代码代码如下:

% 归并两个映射组,注意第二个参数是创建新的映射组,所以只能用 =>
maps:merge(Me, #{ age => 10 }).   
% => #{age => 10,name => "wittyfox"}

 

% 相当于
Me#{ age => 10 }.

 

映射组与列表之间的转换

复制代码代码如下:

% 返回映射元组对的列表
maps:to_list(Me).
% => [{age,19},{name,"wittyfox"}]

 

% 从列表构建映射组
maps:from_list([]).
% => #{}

maps:from_list([{name, "wittyfox"}, {age, 19}]).
% => #{age => 19,name => "wittyfox"}

 

映射组的遍历

复制代码代码如下:

% 对映射组的每对映射执行操作
% X, Y 分别为一对映射的键和值
maps:map(fun (X, Y) -> io:format("~p => ~p~n", [X, Y]) end, Me).  
% age => 19                                             % 输出
% name => "wittyfox"                                    % 输出
% => #{age => ok,name => ok}                            % 返回值

 

% X, Y 分别为一对映射的键和值,V 为上一次迭代的结果,0 为迭代的初始值
% 这里简单的用于每次迭代时值加 1,结果就是映射组的映射数量
maps:fold(fun (X, Y, V) -> V + 1 end, 0, Me).
% => 2

 

映射组中映射的选取

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

复制代码代码如下:

maps:with([], Me).
% => #{}

 

maps:with([age], Me).
% => #{age => 19}

% 键可以不存在
maps:with([aeg], Me).
% => #{}


返回键不再第一个参数的列表中的映射组成的映射组
复制代码代码如下:

maps:without([], Me).
% => #{age => 19,name => "wittyfox"}

 

maps:without([age], Me).
% => #{name => "wittyfox"}

% 键也可以不存在
maps:without([age, neme], Me).
% => #{name => "wittyfox"}


注意

 

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

分享到:
评论

相关推荐

    Erlang list用法

    以下是对标题和描述中提到的Erlang列表函数的详细解释: 1. `all/2`:这个函数用于检查列表`List`中的所有元素是否满足给定的函数`Pred`。如果每个元素作为`Pred`的参数执行都返回`true`,则`all/2`返回`true`;...

    erlang 程序设计 源码

    - **数据结构的使用**:Erlang的列表、元组、映射等数据结构在源码中的应用。 - **模式匹配和函数定义**:了解如何通过模式匹配来简化代码,以及函数多态性的实现。 - **OTP库的使用**:观察源码中是如何利用OTP提供...

    erlang 入门练习

    Erlang支持原子(atom)、整数、浮点数、列表、元组(tuple)、映射(map)等多种数据类型。例如,`client`可能就是一个原子,用于标识模块或进程;列表可以用于存储一系列数据,如`[1, 2, 3]`;而元组`{client, ...

    erlang程序设计

    12. Hot Code Swap:在Erlang中,可以在不中断服务的情况下更新和替换运行中的代码,这是OTP框架的一个强大功能。 学习Erlang可以从基础语法开始,如变量、函数、模块定义,然后逐步掌握进程通信、错误处理、模式...

    Erlang中的基本元素操作小结

    本文详细介绍了Erlang中的基本元素操作,包括元组(tuple)、记录(record)、列表(list)和映射组(map)等。 首先来看元组(tuple)。元组是将固定数量的元素组合成一个单一实体的数据结构,它的一般形式是用大括号{}括...

    nsplit:Erlang映射函数库将一个作业拆分为n个进程并发执行

    nsplit 是一个基于 Erlang/OTP rpc:async_call/4 函数的 n 进程并行/并发映射函数库。 该模块有一个外部功能: npmap(N, F, L): 生成 N 个进程到列表:map(F, L) npmap/3 函数也可作为 nsplit-0.4 的独立模块 npmap...

    map_sets:ssetsmap_setsg

    使用`map_sets`时,需要注意的是,由于Erlang的映射集基于Erlang映射,因此它们支持任意 Erlang 值作为键和值。然而,在`map_sets`中,所有元素都视为键,而对应的值默认为`true`。这意味着,尽管`map_sets`看起来像...

    programming_erlang:章节练习和笔记

    第五章问题据说以下方法存在于 Erlang 的 R17 中但不存在: 地图:to_json(Map) -> Bin 地图:from_json(Bin) -> 地图地图:safe_from_json(Bin) -> 地图似乎没有任何本地方式将 json 转换为 erlang 映射;...

    erlangs_etudes:我对 Ètudes for Erlang 的解决方案

    6. **列表和映射处理**:Erlang提供了丰富的内置函数来处理列表和映射,如`lists:map/2`、`lists:filter/2`等,它们在解决实际问题中非常常用。 7. **模块和导出**:Erlang通过模块组织代码,学习如何合理地划分...

    ScalaVsErlang.pptx

    1. 列表推导:在 Erlang 中,列表推导通常通过列表解析和 `lists:map` 函数来实现,如示例所示,将列表中的每个元素加 1。而在 Scala 中,列表推导可以通过 `for` 循环和 `yield` 关键字来完成,或者使用 `map` 函数...

    tracemap:使用 graphviz 创建 Erlang 消息传递的可视化

    TraceMap 尝试制作进程之间传递的消息的映射。 目前,它可以工作,但可以扩展和改进并使其更加可靠。 不要在生产系统上运行它! 用法 在二郎中: tracemap:map(ranch). ... time passes, and a few ...

    erlCnpj:用于验证 CNPJ 编号的 Erlang 函数

    Erlang 的函数式特性使得编写这种验证函数非常简洁和直观,因为它支持对列表进行高阶操作,如映射(map)、折叠(fold)等,这些都可用于处理CNPJ验证的数学运算。 在压缩包 `erlCnpj-master` 中,可能包含以下文件...

    云计算最新论文-中文

    MapReduce将大规模数据处理分解为两个阶段:Map(映射)和Reduce(化简),简化了处理海量数据的工作流程,常用于云计算平台的数据分析任务。 第三篇未命名的论文(0927302.pdf)可能是对某一特定云计算技术或趋势...

    exjson:Elixir中的JSON解析器和genarator

    标签中的"ElixirErlang"表明Exjson是基于ErlangVM(BEAM)的,这使得它能充分利用并发性,因为ErlangVM天生支持轻量级进程和消息传递。这在处理大量并发请求时尤其有用,比如在一个高负载的Web服务器上,Exjson可以...

    8种Nosql数据库系统对比

    本文将详细介绍八种主流NoSQL数据库系统——Cassandra、MongoDB、CouchDB、Redis、Riak、Membase、Neo4j和HBase,并对其特性进行比较。 #### 1. CouchDB - **语言**:Erlang - **特点**: - 数据一致性 - 易于...

    thrift入门学习教程

    - **Container**:容器类型,包括列表(List)、集合(Set)和映射(Map)。 - **Exception**:异常类型,用于处理服务调用过程中可能出现的错误。 - **Service**:定义对象的接口和服务,包括一系列方法。 **4. 协议** ...

    巫术:莫纳德人和其他长生不老药

    在Elixir中,所有实现了`Map`协议的类型都可以视为Functor,因为它们可以使用`Map.map/2`函数。 "Applicative Functor"是一种更强大的Functor形式,它允许我们在容器内组合函数应用。在Elixir中,`&Kernel.apply/2`...

Global site tag (gtag.js) - Google Analytics