Удалить дубликаты элементов из списка в 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 ]).