【问题标题】:Check if all elements in list have a :ok element检查列表中的所有元素是否都有 :ok 元素
【发布时间】:2019-12-22 04:11:54
【问题描述】:

我有一个这样的元组列表

[
    {:ok, {"0000 0000 "}},
    {:ok, %{AM01: %{"C4" => "1111", "C5" => "1"}}},
    {:ok, %{AM04: %{"C2" => "2222", "C6" => "2"}}}
]

元组的第一个元素:ok表示映射ok。

我怎样才能把这个列表减少到一个这样的列表

[:ok, :ok, :ok]

因为在此转换之后,我将检查 Enum.all 是否一切正常?

【问题讨论】:

    标签: functional-programming elixir list-comprehension


    【解决方案1】:

    另一种选择:

      def check_ok([]), do: true
      def check_ok([{:ok, _} | tail]), do: check_ok(tail)
      def check_ok(_), do: false
    

    只要在列表的每个元素中找到:ok,空列表最终将匹配(第 1 条)并返回 true。否则,当找到 :ok 以外的东西时,递归将立即结束,函数将返回 false(第 3 条)。

    【讨论】:

      【解决方案2】:

      @JustinWood 展示了最惯用的 方法。

      最惯用的 方法可能是使用Kernel.match?/2,它基本上是两个true/false 子句的syntactic sugar

      Enum.all?(input, &match?({:ok, _}, &1))
      #⇒ true
      

      获取所有:ok 通常使用Kernel.SpecialForms.for/1 列表解析来完成,它在一个循环中过滤和映射:

      for {:ok, _} <- input, do: :ok 
      #⇒ [:ok, :ok, :ok]
      

      【讨论】:

      • 很好,我不知道match
      【解决方案3】:

      使用elem/2,您可以像这样缩小地图:

      Enum.map(foo, &elem(&1, 0))
      > [:ok, :ok, :ok]
      

      或者直接使用all?

      Enum.all?(foo, &elem(&1, 0) == :ok)
      > true
      

      【讨论】:

        【解决方案4】:

        您可以立即使用Enum.all?/2,而不是遍历列表以转换为原子列表。

        result = [
          {:ok, {"0000 0000 "}},
          {:ok, %{AM01: %{"C4" => "1111", "C5" => "1"}}},
          {:ok, %{AM04: %{"C2" => "2222", "C6" => "2"}}}
        ]
        
        Enum.all?(result, fn
          {:ok, _} -> true
          _ -> false
        end)
        

        【讨论】:

          猜你喜欢
          • 2020-06-25
          • 2021-12-27
          • 2015-10-03
          • 2011-04-20
          • 2011-07-13
          • 2012-05-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多