簡體   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