Удалить дубликаты элементов из списка в Erlang
Как удалить дубликат из списка в Erlang?
Предположим, у меня есть список вроде:
[1,1,2,3,4,5,5,6]
Как я могу получить:
[1,2,3,4,5,6]
Ответы
Ответ 1
Вы можете использовать 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], больше не дублирует и не сортирует.
Ответ 2
И для тех, кто хочет сохранить порядок списка:
remove_dups([]) -> [];
remove_dups([H|T]) -> [H | [X || X <- remove_dups(T), X /= H]].
Ответ 3
Возможное решение, которое Preserve the order of the elements
поможет вам научиться манипулировать списками, будет включать в себя две функции:
delete_all(Item, [Item | Rest_of_list]) ->
delete_all(Item, Rest_of_list);
delete_all(Item, [Another_item| Rest_of_list]) ->
[Another_item | delete_all(Item, Rest_of_list)];
delete_all(_, []) -> [].
remove_duplicates(List)-> removing(List,[]).
removing([],This) -> lists:reverse(This);
removing([A|Tail],Acc) ->
removing(delete_all(A,Tail),[A|Acc]).
Чтобы проверить,
Eshell V5.9 (abort with ^G)
1> mymod:remove_duplicates([1,2,3,1,2,4,1,2,1]).
[1,2,3,4]
2>
Ответ 4
Я бы сначала сделал что-то вроде этого, чтобы сохранить порядок, хотя не рекомендуется. Помните, что 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
)).
Ответ 5
Модуль 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)).
Ответ 6
по моему мнению, лучший вариант - использовать lists:usort()
Но если вы не хотите использовать BIF, и хотите, чтобы список был отсортирован, я предлагаю версию быстрого сортировки, в этой реализации вы получите список, отсортированный без повторяющихся значений.
unique_sort([]) -> [];
unique_sort([Pivot|T]) ->
unique_sort ([X || X <- T, X < Pivot ) ]++
[Pivot] ++
unique_sort ([X || X <- T, X > Pivot ]).