[英]Reversing list with recursion in Elixir
我的任务是获取一个列表,然后使用一个参数递归地反转它。 我得到的是这个解决方案:
def reverse(l) do
[head | tail] = l
cond do
tail == [] ->
head
true ->
[reverse(tail) , head]
end
end
我试图拥有一个 | 而不是逗号中的真实陈述,但无济于事。 这个解决方案的问题是它在输入 [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
我个人喜欢以这种方式使用模式匹配而不是 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]]
并返回[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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.