2012-12-02 55 views
11

Làm cách nào để xóa bản sao khỏi danh sách trong Erlang?Xóa các phần tử trùng lặp khỏi danh sách trong Erlang

Giả sử tôi có một danh sách như:

[1,1,2,3,4,5,5,6] 

Làm thế nào tôi có thể nhận được:

[1,2,3,4,5,6] 
+0

Danh sách đầu vào đã được sắp xếp chưa? –

+0

Và trật tự có quan trọng không? Tôi có thể sắp xếp lại các yếu tố không? –

Trả lời

33

Bạn có thể sử dụng sets, ví dụ:

my_nonDuplicate_list1() -> 
    List = [1,1,2,3,4,5,5,6], 
    Set = sets:from_list(List), 
    sets:to_list(Set). 

lợi nhuận này [1, 2,3,4,5], không còn bản sao nữa, nhưng hầu như không được sắp xếp.

Một khả năng mà không sử dụng sets sẽ là:

my_nonDuplicate_list2() -> 
    List = [1,1,2,3,4,5,5,6], 
    lists:usort(List). 

Trong trường hợp này nó sẽ trả về [1,2,3,4,5], không có thêm bản sao và được sắp xếp.

1

Một giải pháp có thể là sẽ Preserve the order of the elements để giúp bạn học cách thao tác danh sách, sẽ bao gồm hai chức năng:

 
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]). 

Để kiểm tra,

 
Eshell V5.9 (abort with ^G) 
1> mymod:remove_duplicates([1,2,3,1,2,4,1,2,1]). 
[1,2,3,4] 
2> 

8

Và đối với những người tìm kiếm để giữ gìn trật tự của danh sách:

remove_dups([]) -> []; 
remove_dups([H|T]) -> [H | [X || X <- remove_dups(T), X /= H]]. 
0

Tôi sẽ làm điều gì đó như thế này lúc đầu để giữ gìn trật tự, mặc dù đó là không được đề xuất. Hãy nhớ rằng AddedStuff ++ Accumulator là OK nhưng Accumulator ++ AddedStuff thực sự là xấu.

rm_dup(List) -> 
    lists:foldl(
     fun(Elem, Acc) -> 
      case lists:member(Elem, Acc) of 
       true -> 
        Acc; 
       false -> 
        AcC++ [Elem] 
      end 
     end, [], List 
    ). 

Giải pháp này là hiệu quả hơn nếu bạn muốn giữ gìn trật tự:

rm_dup(List) -> 
    lists:reverse(lists:foldl(
     fun(Elem, Acc) -> 
      case lists:member(Elem, Acc) of 
       true -> 
        Acc; 
       false -> 
        [Elem] ++ Acc 
      end 
     end, [], List 
    )). 
0

Mô-đun sets có hai chức năng có thể được sáng tác và thực hiện công việc một cách hiệu quả: sets:from_list/1 trả về một tập với tất cả các phần tử của một danh sách (không có phần tử trùng lặp nào từ định nghĩa) và sets:to_list/1 trả về một danh sách với các phần tử của một tập hợp. Dưới đây là một ví dụ về sử dụng:

4> sets:to_list(sets:from_list([1,1,2,3,4,5,5,6])). 
[3,6,2,5,1,4] 

Chúng ta có thể xác định các chức năng như

nub(L) -> sets:to_list(sets:from_list(L)). 
+3

Xin vui lòng thêm làm rõ cho câu trả lời của bạn –

+0

Tôi đã chỉnh sửa câu trả lời của tôi, tôi hy vọng là đủ. – aherranz

0

cho ý kiến ​​của tôi, lựa chọn tốt nhất là sử dụng lists:usort()

Nhưng trong trường hợp bạn không muốn để sử dụng BIF, và bạn muốn danh sách được sắp xếp, tôi đề nghị một phiên bản sắp xếp nhanh, trong triển khai này, bạn sẽ nhận được danh sách được sắp xếp mà không có giá trị trùng lặp.

unique_sort([]) -> []; 
unique_sort([Pivot|T]) -> 
unique_sort ([X || X <- T, X < Pivot) ]++ 
[Pivot] ++ 
unique_sort ([X || X <- T, X > Pivot ]). 
Các vấn đề liên quan