[elixir! #0038] Map 的玩法

news/2024/6/30 18:30:50 标签: 数据结构与算法

图片描述

前言

Map 是 elixir 中经常会用到的一种 key-value 数据结构。
它有着 使用简单,顺序无关,可以用任何值做 key,可模式匹配 等优点。

历史

Map 引入 erlang 的时间并不长,是在 OTP17 中新增的数据结构。
可参看这篇文章

常用操作

elixir 对 Map 的支持非常好,在 Kernel 模块中就提供许多操作 Map 的函数。

    iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}

    iex> pop_in(users, ["john", :age])
    {27, %{"john" => %{}, "meg" => %{age: 23}}}

    iex> put_in(users, ["john", :age], 28)
    %{"john" => %{age: 28}, "meg" => %{age: 23}}

    iex> update_in(users, ["john", :age], &(&1 + 1))
    %{"john" => %{age: 28}, "meg" => %{age: 23}}

    iex> get_in(users, ["john", :age])
    27

    iex> get_and_update_in(users, ["john", :age], &{&1, &1 + 1})
    {27, %{"john" => %{age: 28}, "meg" => %{age: 23}}}

此外,还可以这样访问 Map 中的某个值(使用第二种方法时 key 必须为 atom):

    iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
    iex> users["john"][:age]
    27

    iex> map1 = %{a: %{b: 1}, c: 2}
    iex> map1.a.b
    1

还可以这样修改一个 map (key 必须为已经存在的,且必须为 atom):

    iex> map2 = %{a: 1, b: 2}
    iex> %{map2 | a: 3}
    %{a: 3, b: 2}

struct

为了给 Map 增添编译时的结构检查, 以及设置默认值的功能,elixir 提供了 struct。
struct 即是带有 :__struct__ key 的 map。要使用struct, 必须先定义:

    iex> defmodule User do
    ...> defstruct name: 123
    ...> end

    iex> user = %User{}
    %User{name: 123}
    iex> user.__struct__
    User
    iex> %{__struct__: User, name: 456}
    %User{name: 456}

注意,一个 struct 模块需要实现了 Access Behaviour 之后,才可以使用
put_in 等函数。

MapSet

有时,我们会需要这样一种数据结构:一个无序列表,里面的所有元素都是唯一的。
elixir 在 Map 的基础上实现了 MapSet。

它的原理很简单:

iex> MapSet.new([123, :a, "hello"])
#MapSet<[123, :a, "hello"]>

iex> %MapSet{map: %{123 => [], :a => [], "hello" => []}}
#MapSet<[123, :a, "hello"]>

Range

Range 也是一种 struct。

    iex> %Range{first: 1, last: 100}
    1..100

其他

  • 模式匹配时,%{} 可以匹配任意的 Map,包括 struct 和 MapSet。

  • 两个 Map 之间比较大小时,首先比较 key 的个数,然后是 key 的大小,
    最后是 value 的大小。比较 key 的大小时,浮点数永远大于整数:

    iex> a = %{1.1 => []}
    %{1.1 => []}
    iex> b = %{2 => []}
    %{2 => []}
    iex> a > b
    true

http://www.niftyadmin.cn/n/1175974.html

相关文章

android方法被调用两次,安卓:如果使用imeOptions方法被调用了两次

........android:hint"string/email"android:imeOptions"actionSend"/>...android:onClick"sendMessage" <<android:text"string/send" />然后在代码绑定&#xff1a;((EditText) findViewById(R.id.email)).setOnEditorA…

【译】 沙箱中的间谍 - 可行的 JavaScript 高速缓存区攻击

2019独角兽企业重金招聘Python工程师标准>>> 王龑 — MAY 27, 2015 原文连接 The Spy in the Sandbox – Practical Cache Attacks in Javascript 相关论文可在 https://github.com/wyvernnot/cache_attack_in_javascript 下载 作者和单位 Yossef Oren (yos AT cs.c…

JDBC流程

//加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); //连接数据库 Connection connection DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名字", "user", "password"); //创建preparedStatement Prepared…

综合任务1:定时闹铃

完成一下任务&#xff1a;比较简单的综合的任务&#xff1a; 1、定时器倒计时闹铃&#xff1b; 最多用5个按键控制&#xff1b;按键具备短按&#xff0c;长按的功能&#xff1b; 可以控制两个闹铃&#xff1b; 可以控制两个闹铃的时间&#xff0c;时分秒都能控制调节&#xff1…

设置归档目标+查看归档目标+设置归档日志名称

设置归档目标 归档目标:存放归档日志文件的目录&#xff0c;一个数据库可以有多个归档目标&#xff0c;在创建数据库的时候默认设置了归档目标. 设置归档目标语法 alter system set log_archive_dest_N ’{location|server}directory’&#xff1b; directory&#xff1a;磁…

c语言第六章条件型循环结构,C语言程序设计(六)

第六章 循环控制结构循环结构&#xff1a;需要重复执行的操作被重复执行的语句序列称为循环体计数控制的循环条件控制的循环当型循环结构直到型循环结构forwhiledo-whilewhile(循环控制表达式){语句序列}计算循环控制表达式的值&#xff0c;如果循环控制表达式的值为真&#xf…

java 如何把自己写的泪打成jar包,如何放入classpath让其他人可以使用

定位到要打包的上一层路径&#xff0c;执行jar -cvf test.jar *.*(输入需要打包的内容&#xff0c;此为所有内容) 在你要打包的文件夹同级目录下回生成该文件夹名字的jar包了 其他人使用时&#xff0c;在classpath里加上该路径即可,".;"在加上该jar包的位置。 转载于…

编码器改造,得到方向和脉冲

网上有比较多方案&#xff0c;就是利用D触发器&#xff0c;将脉冲AB相两个输入&#xff0c;然后如果A、B两个相序改变&#xff0c;那么输出的Q端的电平发生改变。 前面的是施密特整型电路&#xff0c;由于带编码的电机编码电路部分已经带了整型&#xff0c;所以可以不用这个。…