在 Elixir 中使用递归反转列表
Reversing list with recursion in Elixir
我的任务是获取一个列表,然后使用一个参数递归地反转它。
我得到的是这个解决方案:
def reverse(l) do
[head | tail] = l
cond do
tail == [] ->
head
true ->
[reverse(tail) , head]
end
end
我试过一个 |而不是 true 语句中的逗号,但无济于事。
这个解决方案的问题是它在输入 [1,2,3,4,5] 时打印出以下内容:
[[[[5, 4], 3], 2], 1]
除了返回列表的最终值外,它实际上并没有添加头部部分到列表中。 (在本例中为 5)
不能像在 [reverse(tail), head]
.
中那样对 [list, elem]
进行隐式扁平化
前者是一个列表,这就是您收到嵌套列表的原因。
解决该问题的一种方法是使用 reverse(tail) ++ [head]
将一个列表添加到另一个列表。虽然它效率不高,因为它会在每个步骤中生成新列表 并且 不是尾递归的。
正确的解决方案是引入一个累加器来收集处理过的项目
def reverse(input, acc \ [])
def reverse([], acc), do: acc
def reverse([head | tail], acc) do
reverse(tail, [head | acc])
end
reverse([1, 2, 3])
#⇒ [3, 2, 1]
我个人喜欢以这种方式使用模式匹配而不是 cond,因为我觉得这样更容易推理它。
defmodule M do
def reverse(list) do
reverse_helper(list, [])
end
defp reverse_helper([], reversed) do
reversed
end
defp reverse_helper([h|t], reversed) do
reverse_helper(t, [h|reversed])
end
end
要修复您的解决方案,您可以使用 List.flatten
:
@spec reverse(list()) :: list()
def reverse([]), do: []
def reverse([head | tail]) do
cond do
tail == [] ->
[head]
true ->
List.flatten(reverse(tail) ++ head)
end
end
Flatten 例如需要 [1, [2]]
和 returns [1, 2]
。
但这种解决方案效率不高。您可以使用@aleksei-matiushkin 解决方案,也可以使用尾递归的 foldl:
@spec reverse_fold(list()) :: list()
def reverse_fold(l) do
List.foldl(l, [], fn x, acc ->
[x | acc]
end)
end
我的任务是获取一个列表,然后使用一个参数递归地反转它。 我得到的是这个解决方案:
def reverse(l) do
[head | tail] = l
cond do
tail == [] ->
head
true ->
[reverse(tail) , head]
end
end
我试过一个 |而不是 true 语句中的逗号,但无济于事。 这个解决方案的问题是它在输入 [1,2,3,4,5] 时打印出以下内容:
[[[[5, 4], 3], 2], 1]
除了返回列表的最终值外,它实际上并没有添加头部部分到列表中。 (在本例中为 5)
不能像在 [reverse(tail), head]
.
[list, elem]
进行隐式扁平化
前者是一个列表,这就是您收到嵌套列表的原因。
解决该问题的一种方法是使用 reverse(tail) ++ [head]
将一个列表添加到另一个列表。虽然它效率不高,因为它会在每个步骤中生成新列表 并且 不是尾递归的。
正确的解决方案是引入一个累加器来收集处理过的项目
def reverse(input, acc \ [])
def reverse([], acc), do: acc
def reverse([head | tail], acc) do
reverse(tail, [head | acc])
end
reverse([1, 2, 3])
#⇒ [3, 2, 1]
我个人喜欢以这种方式使用模式匹配而不是 cond,因为我觉得这样更容易推理它。
defmodule M do
def reverse(list) do
reverse_helper(list, [])
end
defp reverse_helper([], reversed) do
reversed
end
defp reverse_helper([h|t], reversed) do
reverse_helper(t, [h|reversed])
end
end
要修复您的解决方案,您可以使用 List.flatten
:
@spec reverse(list()) :: list()
def reverse([]), do: []
def reverse([head | tail]) do
cond do
tail == [] ->
[head]
true ->
List.flatten(reverse(tail) ++ head)
end
end
Flatten 例如需要 [1, [2]]
和 returns [1, 2]
。
但这种解决方案效率不高。您可以使用@aleksei-matiushkin 解决方案,也可以使用尾递归的 foldl:
@spec reverse_fold(list()) :: list()
def reverse_fold(l) do
List.foldl(l, [], fn x, acc ->
[x | acc]
end)
end