坚强00CSDN 2019-06-21
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}
为了给 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
等函数。
有时,我们会需要这样一种数据结构:一个无序列表,里面的所有元素都是唯一的。
elixir 在 Map 的基础上实现了 MapSet。
它的原理很简单:
iex> MapSet.new([123, :a, "hello"]) #MapSet<[123, :a, "hello"]> iex> %MapSet{map: %{123 => [], :a => [], "hello" => []}} #MapSet<[123, :a, "hello"]>
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