我正在尝试实现一个名为even/2
的函数,该函数接受一个数字列表并返回一个等效列表,但所有偶数均已加倍。我应该使用
函数rem(n, k)
将n
除以k
时返回提醒。
我了解/2
表示需要两个参数。
我试图通过使用匿名函数来检查列表中每个元素的其余部分是否均匀来解决它,但是我不知道如何将其放置在新列表中然后输出。
答案 0 :(得分:3)
一个人可以在守卫中使用rem/2
:
Enum.map(input, fn
even when rem(even, 2) == 0 -> even * 2
odd -> odd
end)
答案 1 :(得分:1)
更新/重写:使用该尾部递归
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 :(得分:1)
首先,使用一个参数执行此操作的简单方法:
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
是一种保护措施,这意味着只有在该函数子句为true时(在这种情况下,列表的第一项是偶数),该子句才会被执行。
然后,我们返回一个由可能加倍的值组成的新列表,并使用递归来计算列表的其余部分。
以上方法在调用堆栈中建立结果。我怀疑您被要求使用两个参数的原因是为了利用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]
答案 3 :(得分:1)
在这里,您可以找到最佳的实现方式: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
答案 4 :(得分:1)
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])