【问题标题】:How to understand get value from map by its key in Elixir如何通过 Elixir 中的 key 从 map 中获取价值
【发布时间】:2018-08-13 11:38:17
【问题描述】:

我是 Elixir 的新手,对地图键有疑问。我的地图定义如下:

a = %{"key" => 1}

我可以通过a["key"] 访问该值,但不能通过a.key 访问。如果我将地图定义为a = %{key: 1},那么我可以通过a.key 获取值。我想知道这两种声明键的方式有什么不同。

如果我有一个接受a["key'] 密钥的函数,并且我有一个定义为a = %{key: 1} 的映射,我该如何将此变量传递给函数?

例如,我有以下功能:

def fun1(data) do
    data.key ... // access key by atom
done

我有一个变量数据,它使用字符串作为键。如何将此变量传递给函数?

【问题讨论】:

  • 鉴于您在下方的 cmets,您看起来不像是在共享您的实际代码。没有所有细节,很难回答您的问题。

标签: elixir


【解决方案1】:

这是用于您的密钥的两种不同类型。

  • %{"key" => 1} 正在使用字符串作为键。
  • %{key: 1}%{:key => 1} 的简写,它使用原子作为键。

如果键有原子,则只能使用map.key 语法。

【讨论】:

    【解决方案2】:

    这两种访问值的方式都是 Map.get/2 函数的语法糖。

    所以两者之间的区别在于原子不会被垃圾回收,它们由 erlang VM 进行了优化,用于模式匹配之类的事情。

    字符串是更通用的,所以因为优化你应该总是尝试使用原子作为键,如果可以的话。

    现在我不知道我是否理解了你的最后一个问题,但是在那个函数中获取你想要的键的一个很好的“erlang”方法是:

    作为原子:

    def fun1(%{key: value}) do
        value 
    end
    

    作为字符串:

    def fun1(%{"key" => value}) do
        value 
    end
    

    在这两种情况下,它只会在匹配模式时进入函数,并且您的值将在函数内部已经可用。

    【讨论】:

      【解决方案3】:
      • a = %{"key": 12}使用string作为key,只能使用a["key"]访问。

      • a = %{key: 12}使用atom作为key,可以使用a[:key]a.key访问。

      注意,当map中没有这个key时,a[:key]会返回nil,而a.key会抛出KeyError

      iex(1)> a = %{}
      %{}
      iex(2)> a[:not_exist]
      nil
      iex(3)> a.not_exist
      ** (SyntaxError) iex:7: syntax error before: not_exist
      

      【讨论】:

        【解决方案4】:
        def fun1(data) do
            data.key ... // access key by atom
        done
        

        ...我有一个变量数据,它使用字符串作为键。如何将此变量传递给函数?

        我的.exs:

        defmodule Stuff do
        
          def fun1(data) do
            data.a   #access key by atom
          end
        
        end
        

        在外壳中:

        ~/elixir_programs$ iex my.exs
        Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
        
        Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)
        
        iex(1)> data = %{"a" => 1, "b" => 2}                                                 %{"a" => 1, "b" => 2}
        
        iex(2)> new_data =  Enum.into(data, %{}, fn {key, val} -> {String.to_atom(key), val} end)
        %{a: 1, b: 2}
        
        iex(3)> Stuff.fun1 new_data                                                          1   
        
        iex(4)> 
        

        【讨论】:

        • 我会避免建议使用String.to_atom/1。原子不是垃圾收集的。您可以OOM机器或溢出原子表。
        • 在我看来,过早的优化。如果你来了,就穿过那座桥。
        • 至少应该在答案中提及。您实际上想要使用该功能是非常罕见的。
        • 如果地图是嵌套的怎么办?你的方法支持嵌套地图吗?
        • @ZhaoYi,与其边走边编,不如先贴一个简单的例子来模拟你的问题——显然,一键映射不是你的数据好像。而且,不,我的答案不支持嵌套地图,因为 val 可能是地图,而代码对 val 没有任何作用。
        猜你喜欢
        • 2021-07-24
        • 1970-01-01
        • 2021-01-26
        • 2019-02-02
        • 2018-04-18
        • 2015-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多