Как удалить дубликат из списка в 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], больше не дублирует и не сортирует.
И для тех, кто хочет сохранить порядок списка:
remove_dups([]) -> [];
remove_dups([H|T]) -> [H | [X || X <- remove_dups(T), X /= H]].
Возможное решение, которое 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>
Я бы сначала сделал что-то вроде этого, чтобы сохранить порядок, хотя не рекомендуется. Помните, что 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
)).
Модуль 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 ]).