假设:
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}]]
答案 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