Elixir Credo - 如何使用一个 Enum.reject/2 而不是 Enum.reject/2 |> Enum.reject/2
Elixir Credo - How to use one Enum.reject/2 instead of Enum.reject/2 |> Enum.reject/2
如果我收到像下面这样的 credo-refactoring opportunities 警告,我该怎么办?
One `Enum.reject/2` is more efficient than `Enum.reject/2 |> Enum.reject/2`
例如,如何使用 one Enum.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
一个简单的方法是:
(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) 复杂度。
可以用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]
如果我收到像下面这样的 credo-refactoring opportunities 警告,我该怎么办?
One `Enum.reject/2` is more efficient than `Enum.reject/2 |> Enum.reject/2`
例如,如何使用 one Enum.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
一个简单的方法是:
(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) 复杂度。
可以用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]