将过滤器重写为Elixir中的管道运算符

时间:2018-08-31 20:32:50

标签: elixir

我对Elixir还是陌生的,正在尝试重提一下:

kids = ["Mike", "Paula", "Julia", "Phil"]
Enum.filter(kids, fn(n) -> String.contains? n, "i" end)
# results in: ["Mike", "Julia", "Phil"]

变成这样

kids |> Enum.filter String.contains? "i"

不起作用。 -我想念什么?

3 个答案:

答案 0 :(得分:6)

那非常接近,您可以逐步使用它。

  1. kids之前移动|>

    kids |> Enum.filter(fn(n) -> String.contains?(n, "i") end)

  2. 使用capture operator来缩短过滤函数:

    kids |> Enum.filter(&String.contains?(&1, "i"))

希望有帮助!

答案 1 :(得分:1)

在iex上尝试会给我们错误:

iex(4)> kids = ["Mike", "Paula", "Julia", "Phil"]                 
["Mike", "Paula", "Julia", "Phil"]
iex(5)> kids |> Enum.filter String.contains? "i" 
warning: parentheses are required when piping into a function call. For example:

    foo 1 |> bar 2 |> baz 3

is ambiguous and should be written as

    foo(1) |> bar(2) |> baz(3)

Ambiguous pipe found at:
  iex:5

** (UndefinedFunctionError) function String.contains?/1 is undefined or private. Did you mean one of:

      * contains?/2

    (elixir) String.contains?("i")

错误是因为String.contains?/2期望有2个参数,而只给出了一个。 Enum.filter/2的第二个参数也应该是一个函数。因此,要摆脱该错误,您可以编写:

iex(1)> kids = ["Mike", "Paula", "Julia", "Phil"]
["Mike", "Paula", "Julia", "Phil"]
iex(2)> kids |> Enum.filter fn(n) -> String.contains? n, "i" end
warning: parentheses are required when piping into a function call. For example:

    foo 1 |> bar 2 |> baz 3

is ambiguous and should be written as

    foo(1) |> bar(2) |> baz(3)

Ambiguous pipe found at:
  iex:2

["Mike", "Julia", "Phil"]

要使管道明确,并在此过程中消除警告,只需在函数调用周围添加括号:

iex(3)> kids = ["Mike", "Paula", "Julia", "Phil"]               
["Mike", "Paula", "Julia", "Phil"]
iex(4)> kids |> Enum.filter(fn(n) -> String.contains? n, "i" end)
["Mike", "Julia", "Phil"]

答案 2 :(得分:1)

您还可以将comprehensions与过滤器一起使用:

for kid <- kids, String.contains?(kid, "i"), do: kid
["Mike", "Julia", "Phil"]