从列表中筛选单个项目

时间:2017-03-27 20:16:07

标签: list filter elixir enumerable

假设:

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}]]

3 个答案:

答案 0 :(得分:3)

从列表

中查找一个项目

如果您要将列表过滤到只获取一个项目,请使用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))

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

答案 1 :(得分:1)

只需将已过滤的列表导入Enum.at/2

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

无论大小如何,这都将获得筛选列表的第一个元素。

此外,正如Dogbert在评论中提到的那样,您只需使用Enum.find/2代替过滤即可找到第一场比赛。

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

答案 2 :(得分: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