返回Erlang中的相邻重复项

时间:2015-09-18 15:26:07

标签: recursion erlang

我正试图在Erlang中学习递归,而我正在写一本书。 但是当遇到列表并仅返回重复元素的问题时,我正在撞墙。 我尝试编写一个只返回唯一元素的函数,然后将它们从原始列表中删除。

adjacent_dups(L) -> L -- uniques(L).

uniques([])    -> [];
uniques([H|T]) -> [H | [X || X <- uniques(T), X /= H]].

但是当列表结构不合理时,这将无法给出正确的结果。

L = [7,3,4,3]

我的代码将返回

adjacent_dups([7,3,4,3]) -> 3 

我怎样才能获得

adjacent_dups([7,3,4,3]) -> [] 

2 个答案:

答案 0 :(得分:5)

在函数头中使用模式匹配来查找相邻的相同值:

adjacent_dups(L) ->
    adjacent_dups(L, #{}).
adjacent_dups([], Acc) ->
    maps:keys(Acc);
adjacent_dups([H,H|T], Acc) ->
    adjacent_dups(T,maps:put(H,H,Acc));
adjacent_dups([_|T], Acc) ->
    adjacent_dups(T, Acc).

第一个函数adjacent_dups/1是要导出的。其余的adjacent_dups/2是辅助函数。

adjacent_dups/1函数创建一个空映射以传递给adjacent_dups/2作为累加器的初始值。递归函数通常使用累加器。

adjacent_dups/2的第一个句子处理传入列表已用尽或开始时为空的情况。在这种情况下,我们检索累加器映射的键;这些是我们相邻的价值观。

adjacent_dups/2的第二个子句使用模式匹配处理相邻值的大小写。在这种情况下,我们将值作为键和值添加到累加器映射,并使用列表的尾部递归调用自己。使用地图可以消除最终结果中的重复。

adjacent_dups/2的最后一个句子处理一个值没有相邻值的情况;它只是使用列表尾部和未修改的累加器进行递归调用。

答案 1 :(得分:4)

如果您只想要相邻的重复项,可以尝试从列表中成对匹配它们。这是一个让你入门的天真解决方案。它假设重复项只能成对出现(例如,连续三个):

adjacent_dups([]) -> [];
adjacent_dups([A,A|Tail]) -> [A|adjacent_dups(Tail)];
adjacent_dups([_Head|Tail]) -> adjacent_dups(Tail).

如果我们更多地考虑它,我们可能会意识到我们可以以同样的方式处理三元组。通过使这种情况只消耗第一个值并将其他两个返回,我们实际上可以使它足够通用,即使连续存在多于两个。观看魔术:

adjacent_dups([]) -> [];
adjacent_dups([A,A,A|Tail]) -> adjacent_dups([A,A|Tail]);
adjacent_dups([A,A|Tail]) -> [A|adjacent_dups(Tail)];
adjacent_dups([_Head|Tail]) -> adjacent_dups(Tail).

这是输出:

adjacent_dups([1,1,1,1,2,3,4,55,55,6,7,8,8,8,1]).
[1,55,8]