【问题标题】:Convert a map into a keyword list in Elixir在 Elixir 中将地图转换为关键字列表
【发布时间】:2021-12-07 03:40:35
【问题描述】:

我有一张表格的地图:

%{"browser_name" => "Chrome", "platform" => "linux"}

我需要将其转换为关键字列表:

[browser_name: "Chrome", platform: "linux"]

实现这一目标的最佳方法是什么?

【问题讨论】:

    标签: elixir


    【解决方案1】:

    这不可行吗:

     def convert_to_klist(map) do
       Enum.map(map, fn({key, value}) -> {String.to_existing_atom(key), value} end)
     end
    

    【讨论】:

    • 提防String.to_atom/1容易受到atom DoS攻击。
    • 试试这个:String.to_existing_atom/1
    • 请不要在函数名中使用 CamelCase
    【解决方案2】:

    为了以后的读者,我会把它放在这里。

    虽然人们肯定会在这里和那里盲目地调用String.to_atom/1,但这种方法强烈反对,因为它容易受到原子 DoS 攻击。

    这是 Erlang 文档的摘录:

    原子不会被垃圾回收。一旦创建了一个原子,它就永远不会被删除。如果达到原子数限制(默认为 1,048,576),模拟器将终止。

    因此,在连续运行的系统中,将任意输入字符串转换为原子可能很危险。如果只允许某些定义明确的原子作为输入,则可以使用list_to_existing_atom/1 来防范拒绝服务攻击。 (所有允许的原子必须在之前创建,例如,只需在一个模块中使用所有原子并加载该模块。)

    ——http://erlang.org/doc/efficiency_guide/commoncaveats.html#list_to_atom-1

    也就是说,无论您是从外部不受信任的来源(例如,它是调用您的 API 中的参数或其他什么)接收地图,您不得使用String.to_atom/1,而应使用@987654324 @ 代替。

    否则,带有简单随机密钥生成器的入侵者会毫无问题地炸毁您的 ErlangVM

    【讨论】:

      【解决方案3】:

      您可以使用Keyword.new 函数并传入一个转换函数作为第二个参数。

      Keyword.new(%{"browser_name" => "Chrome", "platform" => "linux"}, fn {k,v} -> {String.to_existing_atom(k), v} end)
      > [browser_name: "Chrome", platform: "linux"]
      

      虽然这基本上等同于@NiteRain 接受的答案,但我认为它更明确一些,并向您的代码的未来读者展示了您的意图。

      见:https://hexdocs.pm/elixir/Keyword.html#new/2

      【讨论】:

        【解决方案4】:

        供日后参考。你也可以使用Enum.into/3

        %{"browser_name" => "Chrome", "platform" => "linux"}
        |> Enum.into([], fn {k, v} -> {String.to_existing_atom(k), v} end)
        

        或更短的版本:

        %{"browser_name" => "Chrome", "platform" => "linux"}
        |> Enum.into([], &{String.to_existing_atom(elem(&1,0)), elem(&1,1)})
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-14
          • 1970-01-01
          相关资源
          最近更新 更多