【问题标题】:List of doubled even numbers. Elixir双倍偶数列表。灵药
【发布时间】:2019-03-19 23:24:11
【问题描述】:

我正在尝试实现一个名为even/2 的函数,该函数接受一个数字列表并返回一个等效列表,但其中所有偶数都已加倍。我应该使用 函数rem(n, k),它在将nk 相除时返回提醒。

我理解/2 意味着需要两个参数。

我尝试通过使用匿名函数检查列表中每个元素的余数是否为偶数来解决它,但我不知道如何将其放入新列表中然后输出。

【问题讨论】:

标签: list recursion elixir


【解决方案1】:

可以在守卫中使用rem/2

Enum.map(input, fn
  even when rem(even, 2) == 0 -> even * 2
  odd -> odd
end)

【讨论】:

    【解决方案2】:

    UPDATE/REWRITE:使用尾递归

    defmodule Main do 
    
      def doubleEven( [], output ) do # case of input empty list
        Enum.reverse output
      end
    
      def doubleEven( [head | tail], output ) do # any other length list
        if rem(head, 2) == 0 do 
          doubleEven(tail, [head*2 | output]) 
        else
          doubleEven(tail, [head | output]) 
        end
      end
    
    end  
    

    使用以下方法调用:

    Main.doubleEven( [1,2,3,4,5,6,7,8,9], [] )
    

    和输出

    [1, 4, 3, 8, 5, 12, 7, 16, 9]
    

    【讨论】:

    • 谢谢,但我认为输出只会是偶数,并且需要 2 个参数
    • 修改它来做你想做的并不难。但是,我会更新我的答案以将其拼写出来。
    • 谢谢你,我现在明白了
    • @Maher.Riyadh 非常感谢 - 也许您可以投票并接受我的回答。
    【解决方案3】:

    你可以找到最好的实现:P

    def double_even([]) do [] end
    def double_even([h|t]) do
      case rem(h,2) do
        0 ->
          [h*2|double_even(t)]
        _ ->
          [h|double_even(t)]
      end
    end
    

    【讨论】:

    • 这个函数甚至应该有两个参数,你用一个参数解决了它
    • 不,不应该:3
    • 是的,但我的意思是这个函数可以只用一个参数来实现。
    【解决方案4】:
      def even([], acc), do: Enum.reverse(acc)
      def even([h|t], acc) when rem(h,2) == 0, do: even(t, [2*h|acc])
      def even([h|t], acc), do: even(t, [h|acc])
    

    【讨论】:

      【解决方案5】:

      首先,用一个参数来做这件事的简单方法:

      defmodule Double do
        def double([]), do: []
        def double([head | tail]) when rem(head, 2) == 0, do: [head * 2 | double(tail)]
        def double([head | tail]), do: [head | double(tail)]
      end
      

      这使用参数的模式匹配将列表的第一个元素分配给head 变量。

      when rem(head, 2) == 0 是一个守卫,这意味着这个函数子句只有在它为真时才会被执行(在这种情况下,列表的第一项是偶数)。

      然后我们返回一个包含可能翻倍的值的新列表,并使用递归来计算列表的其余部分。

      上述方法在调用堆栈中建立结果。我怀疑要求您使用两个参数的原因是利用tail-call optimisation,这意味着即使它进行了递归调用,也不会使用额外的堆栈帧。因为我们没有在其中构建结果的调用堆栈,所以我们添加了一个额外的 output 参数并在那里构建它:

      defmodule Double do
        def double([], output), do: Enum.reverse(output)
        def double([head | tail], output) when rem(head, 2) == 0, do: double(tail, [head * 2 | output])
        def double([head | tail], output), do: double(tail, [head | output])
      end
      

      这里我们编写了一个函数,它接受一个input 和一个output 列表。 该函数调用自身,直到input 用尽(是空列表[]),并在output 列表中建立答案,最终返回。在每次调用中,我们将当前项添加到输出列表中。

      iex> Double.double([1,2,3,4], [])
      [1, 4, 3, 8]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-21
        • 1970-01-01
        • 1970-01-01
        • 2013-05-07
        • 2016-10-12
        • 2011-04-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多