Elixir Credo - 如何使用一个 Enum.reject/2 而不是 Enum.reject/2 |> Enum.reject/2



如果我收到下面这样的信任重构机会警告,该怎么办?

One `Enum.reject/2` is more efficient than `Enum.reject/2 |> Enum.reject/2`

例如,如何使用oneEnum.reject/2而不是Enum.reject/2 |> Enum.reject/2重新编码以下函数?

def my_reject_test() do
(1..10)
|> Enum.reject(&(rem(&1, 2) == 0))
|> Enum.reject(&(rem(&1, 3) == 0))
end

您可以使用or/2组合条件:

iex> Enum.reject(1..10, &(rem(&1, 2) == 0 or rem(&1, 3) == 0))
[1, 5, 7]

credo之所以指出这一点,是因为管道两个Enum.reject/2将首先生成一个中间列表,然后再次遍历它:

iex> 1..10
1..10
iex> |> Enum.reject(&(rem(&1, 2) == 0))
[1, 3, 5, 7, 9]
iex> |> Enum.reject(&(rem(&1, 3) == 0))
[1, 5, 7]

一个简单的方法是:

(1..10)
|> Enum.reject(fn x -> rem(x, 2) == 0 || rem(x, 3) == 0 end)
|> IO.inspect()

对于更复杂的场景,我有时会使用Enum.reduce/3,或者考虑添加一个命名的私有函数来执行逻辑(为了可读性(。

这是一个很好的提醒,遍历列表可能会很昂贵(对于长列表(,所以只要可能,您应该尽量减少遍历列表的次数。使用两次Enum.reject/2使算法的复杂度为O(2n(,而仅使用一次使算法的复杂性为O(n(。

最新更新