因此,基本上我尝试使用一些嵌套的递归自己实现flatten函数。问题是我遇到了无限循环,当检查实际的磁头时它是空的。我刚开始学长生不老药,所以请不要对我太苛刻。
defmodule Test do
def custom_flatten list do
custom_flatten list, []
end
def custom_flatten [h|t], accumulator do
custom_flatten [t], [custom_flatten(h) | accumulator]
end
def custom_flatten [], accumulator do
IO.puts "Called empty list match #{accumulator}"
Enum.reverse accumulator
end
def custom_flatten h, accumulator do
[h|accumulator]
end
end
答案 0 :(得分:0)
此行会导致您出现问题:
custom_flatten [t], [custom_flatten(h) | accumulator]
如果函数以[h | t] = [1, 2, 3]
开头,则t
将为[2, 3]
,并将[[2, 3]]
传递给下一个函数。该函数将显示[h | t] = [[2, 3]]
,因此h
将是[2, 3]
,而t
将是[]
,这会将[[]]
传递给下一个函数。然后,您的函数将陷入重复[h | t] = [[]]
的困境,其中h
是[]
,而t
是[]
。
因此,实际上唯一的问题是您不想包装t
。用类似这样的方法替换上面的行应该可以解决无限递归问题。
custom_flatten t, [custom_flatten(h) | accumulator]
答案 1 :(得分:0)
您似乎已经在这样做了,但是一个好的策略是查看官方实现的工作。 Elixir的实现仅calls through至Erlang implementation。这是用Elixir重写的Erlang实现:
def flatten([], acc), do: acc
def flatten([h | t], acc) when is_list(h) do
flatten(h, flatten(t, acc))
end
def flatten([h | t], acc) do
[h | flatten(t, acc)]
end
似乎您的实现存在一些问题。
[t]
(这是一个包含尾部列表的单元素列表),所以终止条件永远不会发生。h
)是否为列表,以决定是否需要另一层递归,或者是否可以直接使用该元素。 ++
)运算符,因为在反向构建时,我们必须动态地将子列表展平,然后将它们连接到累加器(在非反向的Erlang中)实施中,尾部总是先被拉平,因此在这种情况下没有必要)。我们还需要确保只反转最终结果,否则内部列表在递归调用期间也会被反转:def flatten(list) do
list
|> flatten([])
|> Enum.reverse()
end
def flatten([], acc), do: acc
def flatten([h | t], acc) when is_list(h) do
flatten(t, flatten(h, []) ++ acc)
end
def flatten([h | t], acc) do
flatten(t, [h | acc])
end