繁体   English   中英

Elixir 中的递归反转列表

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM