如何在 Elixir 中通过索引同时从列表中删除多个项目?
How do I remove multiple items from a list at the same time by index in Elixir?
这是我要实现的目标:
> a = ["a","b","c","d","e"]
> Enum.reject_multiple(a,[1,3])
["a", "c", "e"]
我能想到的最清晰的方法是包含索引并拒绝所需的项目。
rejected_indices = MapSet.new([1, 3])
["a", "b", "c", "d", "e"]
|> Stream.with_index()
|> Stream.reject(fn {_item, index} -> index in rejected_indices end)
|> Enum.map(&elem(&1, 0))
#=> ["a", "c", "e"]
虽然@BrettBeatty 肯定提供了正确的方法,但我想 post 举例说明如何使用一些元编程魔法通过一次遍历列表来实现它。只是为了举例。
defmodule MyEnum do
defmacro decimate(list, indices) do
quote do
unquote(list)
|> Enum.reduce({0, []}, fn
_, {i, acc} when i in unquote(indices) -> {i + 1, acc}
e, {i, acc} -> {i + 1, [e | acc]}
end)
|> elem(1)
|> Enum.reverse()
end
end
end
require MyEnum
MyEnum.decimate(~w[a b c d e], [1, 3])
#⇒ ["a", "c", "e"]
需要宏才能将 indices
置于守卫状态。
这是我要实现的目标:
> a = ["a","b","c","d","e"]
> Enum.reject_multiple(a,[1,3])
["a", "c", "e"]
我能想到的最清晰的方法是包含索引并拒绝所需的项目。
rejected_indices = MapSet.new([1, 3])
["a", "b", "c", "d", "e"]
|> Stream.with_index()
|> Stream.reject(fn {_item, index} -> index in rejected_indices end)
|> Enum.map(&elem(&1, 0))
#=> ["a", "c", "e"]
虽然@BrettBeatty 肯定提供了正确的方法,但我想 post 举例说明如何使用一些元编程魔法通过一次遍历列表来实现它。只是为了举例。
defmodule MyEnum do
defmacro decimate(list, indices) do
quote do
unquote(list)
|> Enum.reduce({0, []}, fn
_, {i, acc} when i in unquote(indices) -> {i + 1, acc}
e, {i, acc} -> {i + 1, [e | acc]}
end)
|> elem(1)
|> Enum.reverse()
end
end
end
require MyEnum
MyEnum.decimate(~w[a b c d e], [1, 3])
#⇒ ["a", "c", "e"]
需要宏才能将 indices
置于守卫状态。