Return Erlang 中的相邻重复项
Return adjacent duplicates in Erlang
我正在尝试学习 Erlang 中的递归,并且正在阅读一本书。
但是,当我遇到获取列表并仅 returning 重复元素的问题时,我遇到了困难。
我尝试编写一个函数,该函数 return 仅包含唯一元素,然后将它们从原始列表中删除。
adjacent_dups(L) -> L -- uniques(L).
uniques([]) -> [];
uniques([H|T]) -> [H | [X || X <- uniques(T), X /= H]].
然而,当列表结构不正确时,这将不会给出正确的结果。
L = [7,3,4,3]
我的代码会return
adjacent_dups([7,3,4,3]) -> 3
如何获得
adjacent_dups([7,3,4,3]) -> []
如果您只想要相邻的重复项,您可以尝试将它们从列表中成对地进行模式匹配。这是一个让您入门的简单解决方案。它假定重复项仅成对出现(例如,永远不会连续出现三个):
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]
在函数头中使用模式匹配查找相邻的相同值:
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
的最后一个子句处理值没有相邻值的情况;它只是用列表的尾部和一个未修改的累加器进行递归调用。
我正在尝试学习 Erlang 中的递归,并且正在阅读一本书。 但是,当我遇到获取列表并仅 returning 重复元素的问题时,我遇到了困难。 我尝试编写一个函数,该函数 return 仅包含唯一元素,然后将它们从原始列表中删除。
adjacent_dups(L) -> L -- uniques(L).
uniques([]) -> [];
uniques([H|T]) -> [H | [X || X <- uniques(T), X /= H]].
然而,当列表结构不正确时,这将不会给出正确的结果。
L = [7,3,4,3]
我的代码会return
adjacent_dups([7,3,4,3]) -> 3
如何获得
adjacent_dups([7,3,4,3]) -> []
如果您只想要相邻的重复项,您可以尝试将它们从列表中成对地进行模式匹配。这是一个让您入门的简单解决方案。它假定重复项仅成对出现(例如,永远不会连续出现三个):
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]
在函数头中使用模式匹配查找相邻的相同值:
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
的最后一个子句处理值没有相邻值的情况;它只是用列表的尾部和一个未修改的累加器进行递归调用。