【问题标题】:Filtering/Pattern Matching in nested data structure嵌套数据结构中的过滤/模式匹配
【发布时间】:2015-03-30 03:50:39
【问题描述】:

我是 Elixir 的新手,对模式匹配仍然很困惑。

[%{name: "Deutschland", code: "DE"}, %{name: "Frankreich", code: "FR"}]

  def find_by_code([], _name), do: []
  def find_by_code([h | t], query) do
    if h[:code] == query do
      IO.puts("MATCH")
      IO.inspect(h)
    else
      IO.puts ("No match")
      find_by_code(t, query)
    end
  end

这是通过代码查找国家/地区的最佳方式吗?

【问题讨论】:

    标签: list dictionary nested elixir


    【解决方案1】:

    您可以根据需要进行任意深度的模式匹配:

    def find_by_code([], _query),
      do: nil # or whatever you want to mean "not found"
    
    def find_by_code([%{code: query} = country|_t], query),
      do: IO.inspect(country)
    
    def find_by_code([_country|t], query),
      do: find_by_code(t, query)
    

    您还可以将Enum.find/3match?/2 一起使用,这可能更具可读性(如另一个答案中所建议)。

    【讨论】:

    • 这是一个很好的答案,甚至不知道第二种形式是可能的!
    • 很好的答案,一个可以消除警告的小补充。第二个函数子句中的t 变量未使用,因此应指定为_t
    • @b73 不错!我是在手机上写的,所以我什至没有运行它,哎呀 :) 谢谢!
    【解决方案2】:

    你可以这样做:

    countries = [
      %{name: "Deutschland", code: "DE"},
      %{name: "Frankreich", code: "FR"}
    ]
    
    Enum.find(countries, &match?(%{code: "FR"}, &1))
    # %{code: "FR", name: "Frankreich"}
    

    【讨论】:

    • match?/2 宏是不错!我不知道我怎么不知道这件事。谢谢帕特里克!
    • 是的,当我发现它时我也非常兴奋!我首先wrote a macro 这样做。尽管如此,这是我的第一个宏,我在这个过程中学到了很多;-)
    【解决方案3】:

    Elixir 没有内置模式匹配来尝试根据它们的值过滤掉列表中的某些项目。

    您可以编写一个模式匹配来检查单个项目,如下所示:

    match_country_code = fn (%{:code => "DE"} = country) -> country 
                            (_) -> nil
                         end
    

    然后将其传递给 Enum.find:

    lands = [
      %{name: "Deutschland", code: "DE"},
      %{name: "Frankreich", code: "FR"}
    ]
    Enum.find(lands, &(match_country_code.(&1)))
    # => %{code: "DE", name: "Deutschland"}
    

    或者概括地说,你可以:

    lands = [
      %{name: "Deutschland", code: "DE"},
      %{name: "Frankreich", code: "FR"}
    ]
    
    find_by = fn (list, key, val) ->
      Enum.find(list, &(Map.get(&1, key)==val))
    end
    
    find_by.(lands, :name, "DE")
    #=> %{code: "DE", name: "Deutschland"}
    

    更改 find 以过滤并获取结果列表:

    lands = [
      %{name: "Deutschland", code: "DE"},
      %{name: "Germany", code: "DE"},
      %{name: "Frankreich", code: "FR"}
    ]
    
    filter_by = fn (list, key, val) ->
      Enum.filter(list, &(Map.get(&1, key)==val))
    end
    
    filter_by.(lands, :code, "DE")
    #=> [%{code: "DE", name: "Deutschland"}, %{code: "DE", name: "Germany"}]
    

    【讨论】:

      猜你喜欢
      • 2022-01-22
      • 1970-01-01
      • 2017-11-12
      • 2020-03-18
      • 2022-01-11
      • 2015-07-21
      • 2017-12-16
      • 2016-10-29
      • 1970-01-01
      相关资源
      最近更新 更多