maps 是elixir中的一个基础的数据结构,存储格式为key-value(键-值)对,语法为 %{}
map的两个特点:
iex(1)> map = %{:a => 1, 2 => :b}
%{2 => :b, :a => 1}
iex(2)> map[:a]
1
iex(3)> map[2]
:b
iex(4)> map[:b]
nil
iex(5)>
iex(5)> %{:a => a} = %{:a => 1, 2 => :b}
%{2 => :b, :a => 1}
iex(6)> a
1
iex(7)>
iex(14)> map = %{:a => 1, 2 => :b}
%{2 => :b, :a => 1}
iex(15)> %{map | 2 => "two"}
%{2 => "two", :a => 1}
iex(16)> %{map | :c => "two"}
** (KeyError) key :c not found in: %{2 => :b, :a => 1}
(stdlib 4.0.1) :maps.update(:c, "two", %{2 => :b, :a => 1})
(stdlib 4.0.1) erl_eval.erl:309: anonymous fn/2 in :erl_eval.expr/6
(stdlib 4.0.1) lists.erl:1350: :lists.foldl/3
iex(16)>
iex(32)> map1 = %{2 => :a, "hello" => 3, "c" => 3, a: 1, b: 2}
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(33)> map2 = %{x: 1, y: 2}
%{x: 1, y: 2}
Map.delete(map, key): 从指定的map中,删除指定的key, 如果key不存在,不会有任何改变
map1 = %{2 => :a, "hello" => 3, "c" => 3, a: 1, b: 2}
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(34)> Map.delete(map1, 2)
%{:a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(35)
Map.drop(map, keys): 从指定的map中删除指定的一组keys
iex(35)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(36)> Map.drop(map1, ["c", 2])
%{:a => 1, :b => 2, "hello" => 3}
iex(37)>
Map.equal?(map1, map2): 比较2个map是否完全相同;此函数没有太大意义。在使用过程中,要完成此功能,一般使用 ==/2
, ===/2
iex(39)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(40)> map2
%{x: 1, y: 2}
iex(41)> Map.equal?(map1, map2)
false
iex(42)>
Map.fetch!(map, key): 从指定的map中获取指定的key的值;如果map中不包含此key,会有KeyError提示
iex(43)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(44)> map2
%{x: 1, y: 2}
iex(46)> Map.fetch!(map1, :c)
** (KeyError) key :c not found in: %{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
(stdlib 4.0.1) :maps.get(:c, %{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3})
iex(46)>
Map.fetch(map, key): 从指定的map中获取指定的key,如果map中不包含此key,返回状态 :error
这也是与Map.fetch!/2不同的地方
iex(51)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(52)> Map.fetch(map1, 2)
{:ok, :a}
iex(53)> Map.fetch(map1, :c)
:error
iex(54)>
Map.filter(map, fun): 对map按照函数中的筛选条件进行筛选,函数返回值为true则通过筛选。fun参数为key和value
iex(58)> Map.filter(map1, fn {_key, val} -> is_integer(val) end)
%{:a => 1, :b => 2, "c" => 3, "hello" => 3}
Map.from_struct(struct): 将一个结构转化成map,此函数接受一个module或是一个结构作为参数。
iex(63)> defmodule User do
...(63)> defstruct [:user]
...(63)> end
iex(64)> Map.from_struct(User)
%{user: nil}
iex(65)> Map.from_struct(%User{user: "john"})
%{user: "john"}
iex(66)>
Map.get(map, key, default \ nil): 获取map指定的key的值,如果key的值在map中存在,那将会返回此值;否则 default 被返回,如果default没有提供值,则nil被返回
iex(75)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(76)> Map.get(map1, :a)
1
iex(77)> Map.get(map1, :c) # 没有default返回nil
nil
iex(78)> Map.get(map1, :c, "ccccc") # 有default 返回default的值
"ccccc"
iex(79)>
get_and_update!(map, key, fun) : 获取map中指定key的值并且更新它;此函数的返回值为tuple {key当前的值,修改后的map}
;如果可以的值不存在,则返回KeyError错误;
get_and_update(map, key, fun): 获取map中指定key的值并且更新它;此函数的返回值为tuple {key当前的值,修改后的map}
; 如果key的值不存在,则tuple中的第一个元素为nil,第二个参数为添加了新的key的map;
iex(85)> Map.get_and_update(map1, :c, fn current_value -> {current_value, "t"} end)
{nil, %{2 => :a, :a => 1, :b => 2, :c => "t", "c" => 3, "hello" => 3}}
注意⚠️:2个函数最大的区别就是返回值不同
get_lazy(map, key, fun):获取map中指定的key的值;如果key在map中存在,则返回它对应的值,如果key在map中不存在fun函数执行,并且函数值被返回。
iex(90)> map4 = %{a: 1}
%{a: 1}
iex(91)> fun = fn -> 13 end
#Function<43.3316493/0 in :erl_eval.expr/6>
iex(93)> Map.get_lazy(map4, :a, fun)
1
iex(94)> Map.get_lazy(map4, :b, fun)
13
has_key?(map, key): 判断map中是否包含指定的key,返回 boolean 值
iex(96)> map4
%{a: 1}
iex(97)> Map.has_key?(map4, :a)
true
iex(98)> Map.has_key?(map4, :c)
false
iex(99)>
keys(map):返回 map 中的所有 keys,返回值为 list 格式
iex(100)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(101)> Map.keys(map1)
[2, :a, :b, "c", "hello"]
iex(102)>
merge(map1, map2):合并2个 map 到一个新的map,如果map1中的key与map2中的key重复,则map2中的值覆盖map1中的 值
iex(109)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(110)> map3
%{a: "test"}
iex(111)> Map.merge(map1, map3) # key 为 a 这个map1, map3中都存在,合并后 a 取得map3中的值
%{2 => :a, :a => "test", :b => 2, "c" => 3, "hello" => 3}
merge(map1, map2, fun):合并2个map成一个新的map,用 fun 函数参数来解决合并过程中的冲突
map2中的所有元素都会添加到map1中;当map2与map1中的key重复时,就会调用函数fun;函数fun有3个参数,分别是重复的key,map1中key对应的value,map2中key对应的value。函数的返回值将作为key的value存储在新的map中。
iex(118)> fun = fn _k, v1, v2 -> v1 + v2 end
#Function<40.3316493/3 in :erl_eval.expr/6>
iex(119)> Map.merge(%{a: 1, b: 2}, %{a: 3, d: 4}, fun)
%{a: 4, b: 2, d: 4}
iex(120)>
new(): 返回一个空的map
iex(121)> Map.new()
%{}
iex(122)>
new(enumerable): 返回一个可以枚举的map,如果key重复保留最后一次出现的key的值;
new(enumerable, transform): 通过transformation fun函数创建一个可枚举的map
iex(126)> Map.new([:a, :b], fn x -> {x, x} end)
%{a: :a, b: :b}
iex(127)> Map.new([{:a, 1}, {:b, 2}])
%{a: 1, b: 2}
pop!(map, key): 从map中移除指定的key,如果map中存在此key则返回key对应的值和移除后的map;如果key不存在则会报错 KeyError
iex(132)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(133)> Map.pop!(map1, :a)
{1, %{2 => :a, :b => 2, "c" => 3, "hello" => 3}}
iex(134)> Map.pop!(map1, :d)
** (KeyError) key :d not found in: %{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
(elixir 1.13.4) lib/map.ex:690: Map.pop!/2
iex(134)>
pop(map, key, default \ nil):从map中移除指定的key,如果key存在返回其对应的值,如果key不存在则更新map,添加上此key,default为key的值,default默认为nil。
iex(136)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(137)> Map.pop(map1, :a)
{1, %{2 => :a, :b => 2, "c" => 3, "hello" => 3}}
iex(138)> Map.pop(map1, :c, 3)
{3, %{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}}
iex(139)>
pop_lazy(map, key, fun):返回tuple,如果key在map中存在,返回{value, new_map},new_map为删除掉key后剩余的元素;如果map中不包含key,则返回{fun_result, map},
iex(178)> Map.pop_lazy(map2, :x, fn -> 3 end)
{1, %{y: 2}}
iex(179)> Map.pop_lazy(map2, :z, fn -> 3 end)
{3, %{x: 1, y: 2}}
iex(180)>
put(map, key, value): 将key-value更新到指定的map中,如果key已经存在则更新key的值为value
iex(166)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(167)> Map.put(map1, :c, 3)
%{2 => :a, :a => 1, :b => 2, :c => 3, "c" => 3, "hello" => 3}
iex(168)> Map.put(map1, :a, 3)
%{2 => :a, :a => 3, :b => 2, "c" => 3, "hello" => 3}
iex(169)>
put_new(map, key, value) : 将key-value添加到不存在此key的map中,如果存在则忽略。
iex(169)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(170)> Map.put_new(map1, :a, 3)
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(171)>
put_new_lazy(map, key, fun): 如果key在map中存在,则返回key-value的新map;如果key不存在,则将fun函数的值付值给key更新到map中,返回更新后的map。
iex(173)> map2
%{x: 1, y: 2}
iex(174)> Map.put_new_lazy(map2, :x, fn -> 3 end)
%{x: 1, y: 2}
iex(175)> Map.put_new_lazy(map2, :z, fn -> 3 end)
%{x: 1, y: 2, z: 3}
iex(176)>
reject(map, fun):返回map,其中的元素包含除fun函数返回值为ture的其他元素;功能与filter/2类似
iex(162)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(163)> Map.reject(map1, fn {_key, val} -> is_integer(val) end)
%{2 => :a}
iex(164)>
replace!(map, key, value): 将map中指定key的值替换成value,如果key不存在报错KeyError
replace(map, key, value): 将map中指定key的值替换成value,如果key不存在则忽略。
iex(157)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(158)> Map.replace(map1, 2, "hello") # key为2的值替换成hello
%{2 => "hello", :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(159)> Map.replace(map1, :c, "hello") # key为 :c 在map中不存在,忽略
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(160)>
split(map, keys): 从map中移除指定的keys,keys中的值在map中存在的移除,不存在的忽略;返回值为tuple,第一个元素为从map 中移除的keys-value对, 第二个元素为map移除后剩下的keys;
iex(153)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(154)> Map.split(map1, [:a, :b]) # 从map1中移除a,b
{%{a: 1, b: 2}, %{2 => :a, "c" => 3, "hello" => 3}}
iex(155)>
take(map, keys): 从map中获取指定的keys和值,并且返回一个新的map
iex(149)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(150)> Map.take(map1, [:a, "c"])
%{:a => 1, "c" => 3}
iex(151)> Map.take(map1, [:a, "c", :d]) #map1中不存在 :d 这个key,直接忽略
%{:a => 1, "c" => 3}
iex(152)>
to_list(map): 将map转化成list,如果map中的格式是key-value的格式,则转化成list的格式为{key, value}tuple的格式
update!(map, key, fun): 更新map中key的值,如果key存在则key的值为fun函数的返回值,如果key不存在,报错KeyError;
update(map, key, default,fun): 更新map中指定key的值,如果key存在则key的值为fun函数的返回值;如果key不存在则,在map中添加key,key的值为default;
iex(144)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(145)> Map.update!(map1, :a, &(&1 * 2)) #Map.update/3
%{2 => :a, :a => 2, :b => 2, "c" => 3, "hello" => 3}
iex(146)> Map.update(map2, :c, ":cccc", &(&1 * 3)) #Map.update/4
%{c: ":cccc", x: 1, y: 2}
iex(147)> Map.update(map1, :c, ":cccc", &(&1 * 3))
%{2 => :a, :a => 1, :b => 2, :c => ":cccc", "c" => 3, "hello" => 3}
iex(148)>
values(map): 返回map的所有value
iex(140)> map1
%{2 => :a, :a => 1, :b => 2, "c" => 3, "hello" => 3}
iex(141)> Map.values(map1)
[:a, 1, 2, 3, 3]
iex(142)>