【问题标题】:Filter single item from a List从列表中过滤单个项目
【发布时间】:2017-08-20 16:59:41
【问题描述】:

给定:

iex(9)> list_of_maps = [%{"a" => 1, "b"  => 2, "c" => 3},%{"a" => 66, "b"  => 1, "c" => 9},%{"a" => 66, "b"  => 20, "c" => 8}]

我能做到:

iex(10)> Enum.filter(list_of_maps, &(&1["a"] == 1))                                                                                                                                                                
Enum.filter(list_of_maps, &(&1["a"] == 1))                                                                                                                                                                         
[%{"a" => 1, "b" => 2, "c" => 3}]

然而现在我害怕用每种语言编写的部分 - 获取此列表的第一个值以提取单个项目。

elixir 中是否有一些标准功能可以过滤列表,如果在应用过滤器后只有一个项目,则返回单个项目,或者如果在应用过滤器后返回多个项目,则返回项目列表?喜欢:

iex(11)> Enum.filterr(list_of_maps, &(&1["a"] == 1))                                                                                                                                                                
Enum.filter(list_of_maps, &(&1["a"] == 1))                                                                                                                                                                         
%{"a" => 1, "b" => 2, "c" => 3}

iex(12)> Enum.filterr(list_of_maps, &(&1["a"] == 66))                                                                                                                                                                
Enum.filter(list_of_maps, &(&1["a"] == 66))                                                                                                                                                                         
[%{"a" => 66, "b"  => 1, "c" => 9},%{"a" => 66, "b"  => 20, "c" => 8}]]

【问题讨论】:

  • 仅供参考,如果您只想要第一个,这里有 Enum.find/2
  • 我很好奇你为什么需要这个。这不需要添加一个特殊情况来处理映射列表,并且只映射到您从filterr/2 获取结果后计划调用的任何函数?
  • @Dogbert 不确定我是否正确理解了这个问题,(将“地图列表和仅地图”读取为“地图只是的列表maps' - 但是在选择单个项目的情况下,似乎不需要特殊情况 - 这是预期的。但是我现在可以看到,如果需要单个项目,使用 @ 987654326@ 显示更清晰的预期返回单个项目。

标签: list filter elixir enumerable


【解决方案1】:

elixir 中是否有一些标准功能可以过滤列表,如果只有一个项目,则返回单个项目……如果有很多项目,则返回项目列表

不,但是模式匹配让它变得微不足道:

def single_or_many([single]), do: single
def single_or_many(many), do: many

如果您想特别处理空列表(在“多”情况之前):

def single_or_many([]), do: :nil

那么,函数调用链将是:

list_of_maps
|> Enum.filter(&(&1["a"] == 1))
|> single_or_many

【讨论】:

    【解决方案2】:

    从列表中查找一项

    如果您想过滤列表以只获取一项,请使用Enum.find/2

    Enum.find(list_of_maps, fn m -> m["a"] == 1 end)
    

    获取一个或一组匹配项

    要处理这两种情况,模式匹配是要走的路:

    defmodule MyEnum do
      def filter(list, fun) do
        list
        |> Enum.filter(fun)
        |> normalize
      end
    
      defp normalize([item]), do: item
      defp normalize(list),   do: list
    end
    

    然后你可以像这样使用它:

    MyEnum.filter(list_of_maps, &(&1["a"] == 1))
    

    如果有多个匹配则返回一个列表,如果只有一个匹配则返回地图本身。

    【讨论】:

      【解决方案3】:

      只需将过滤后的列表输入Enum.at/2

      first = list_of_maps |> Enum.filter(&(&1["a"] == 66)) |> Enum.at(0)
      

      这将获得过滤列表的第一个元素,无论大小。

      此外,正如 Dogbert 在 cmets 中提到的,您可以使用 Enum.find/2 而不是 filter 来查找第一个匹配项。

      Enum.find(list_of_maps, &(&1["a"] == 66))
      

      【讨论】:

        猜你喜欢
        • 2015-06-04
        • 2021-02-28
        • 1970-01-01
        • 2020-08-31
        • 2013-04-22
        • 1970-01-01
        • 2011-10-25
        • 1970-01-01
        • 2020-07-08
        相关资源
        最近更新 更多