• Elixir - Map


    Maps

    maps 是elixir中的一个基础的数据结构,存储格式为key-value(键-值)对,语法为 %{}
    map的两个特点:

    • Maps 允许任何值做 key
    • Maps 的 key 不能排序
    • Maps 的语法格式
      当map的key是一个atom时,可以采用key: value的写法,获取时也可以使用map.key的方式获取
      注意⚠️:采用map[:key]获取不存在的值,返回的时nil,采用map.key获取不存在的值,返回的是keyError
      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)>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • Map 模式匹配
      iex(5)> %{:a => a} = %{:a => 1, 2 => :b}
      %{2 => :b, :a => 1}
      iex(6)> a
      1
      iex(7)>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 更新Map的值
      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)>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      注意⚠️:若更新的key,在map中不存在,则会报KeyError。
    • Map module API
      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}
      
      • 1
      • 2
      • 3
      • 4
      • 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)
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      • 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)> 
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      • 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}
        
        • 1
        • 2
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
      • 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)> 
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
      • 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}}
        
        • 1
        • 2

        注意⚠️: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
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • 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}
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • new(): 返回一个空的map

        iex(121)> Map.new()
        %{}
        iex(122)>
        
        • 1
        • 2
        • 3
      • 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}
        
        • 1
        • 2
        • 3
        • 4
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • 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)> 
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      • 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)> 
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
      • 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)>
        
        • 1
        • 2
        • 3
        • 4
        • 5
  • 相关阅读:
    Linux Ubuntu 22.04安装Dash to Panel替换系统自带的dock panel
    bootloader介绍
    【JQuery】扩展BootStrap入门——知识点讲解(一)
    树莓派官方系统自带的gpiozero库教程
    TeamTalk中对一条连接收发消息的封装。
    【导入】spice In 导入网表-device map的设置
    Matlab----程序流程控制
    【数据结构与算法】四、链表相关算法题
    链表OJ题
    Nacos 小bug: application.properties配置未生效,导致端口未生效
  • 原文地址:https://blog.csdn.net/HobbitHero/article/details/126252923