【发布时间】:2012-11-20 07:45:29
【问题描述】:
如何从 Erlang 的列表中删除重复项?
假设我有一个类似的列表:
[1,1,2,3,4,5,5,6]
如何获得:
[1,2,3,4,5,6]
【问题讨论】:
-
输入列表是否已经排序?
-
顺序重要吗?我可以重新排列元素吗?
如何从 Erlang 的列表中删除重复项?
假设我有一个类似的列表:
[1,1,2,3,4,5,5,6]
如何获得:
[1,2,3,4,5,6]
【问题讨论】:
您可以使用sets,例如:
my_nonDuplicate_list1() ->
List = [1,1,2,3,4,5,5,6],
Set = sets:from_list(List),
sets:to_list(Set).
这将返回[1,2,3,4,5],不再重复,但很可能未排序。
不使用sets 的另一种可能性是:
my_nonDuplicate_list2() ->
List = [1,1,2,3,4,5,5,6],
lists:usort(List).
在这种情况下,它返回[1,2,3,4,5],不再重复和排序。
【讨论】:
usort 是 N log N,集合是线性的吗?我想从一个列表到一个集合是线性的,反之亦然,所以也许第一个选项更有效(如果不需要排序)。
模块sets 有两个可以组合并以有效方式完成工作的函数:sets:from_list/1 返回一个包含列表所有元素的集合(定义中没有重复的元素),sets:to_list/1 返回一个包含一组元素的列表。下面是一个使用示例:
4> sets:to_list(sets:from_list([1,1,2,3,4,5,5,6])).
[3,6,2,5,1,4]
我们可以将函数定义为
nub(L) -> sets:to_list(sets:from_list(L)).
【讨论】:
在我看来,最好的选择是使用lists:usort()
但是,如果您不想使用 BIF,并且希望对列表进行排序,我建议使用快速排序的版本,在此实现中,您将获得排序后的列表而没有重复值。
unique_sort([]) -> [];
unique_sort([Pivot|T]) ->
unique_sort ([X || X <- T, X < Pivot ) ]++
[Pivot] ++
unique_sort ([X || X <- T, X > Pivot ]).
【讨论】:
我会首先做这样的事情来保持秩序,尽管它不推荐。请记住AddedStuff ++ Accumulator 可以,但Accumulator ++ AddedStuff 真的很糟糕。
rm_dup(List) ->
lists:foldl(
fun(Elem, Acc) ->
case lists:member(Elem, Acc) of
true ->
Acc;
false ->
Acc ++ [Elem]
end
end, [], List
).
如果你想保持秩序,这个解决方案效率更高:
rm_dup(List) ->
lists:reverse(lists:foldl(
fun(Elem, Acc) ->
case lists:member(Elem, Acc) of
true ->
Acc;
false ->
[Elem] ++ Acc
end
end, [], List
)).
【讨论】:
对于那些希望保持列表顺序的人:
remove_dups([]) -> [];
remove_dups([H|T]) -> [H | [X || X <- remove_dups(T), X /= H]].
【讨论】:
distinct 或remove_dups 函数的要点是保留顺序,否则使用集合或有序集合始终是一种选择。跨度>
Preserve the order of the elements 帮助您学习如何操作列表的可能解决方案将涉及两个功能:
为了测试,
Eshell V5.9(使用 ^G 中止) 1> mymod:remove_duplicates([1,2,3,1,2,4,1,2,1])。 [1,2,3,4] 2>【讨论】: