6

Erlangのリストを考えると、例:

L = [foo, bar, foo, buzz, foo].

再帰関数を使用して、そのリストの一意のアイテムのみを表示するにはどうすればよいですか?リスト関数の1つ(存在する場合)のような組み込み関数を使用したくありません。

私の例では、行きたい場所は、次のような新しいリストになります。

SL = [bar, buzz].

私の推測では、フィルターを適用する前に、クイックソート機能を使用してリストを最初にソートしますか?

どんな提案も役に立ちます。この例は、Cesarini&Thompsonの優れた「ErlangProgramming」本の第3章の演習のバリエーションです。

4

9 に答える 9

7

私はこれを提案します:

unique(L) ->
    unique([],L).
unique(R,[]) -> R; 
unique(R,[H|T]) ->
    case member_remove(H,T,[],true) of
        {false,Nt} -> unique(R,Nt);
        {true,Nt} -> unique([H|R],Nt)
    end.

member_remove(_,[],Res,Bool) -> {Bool,Res};
member_remove(H,[H|T],Res,_) -> member_remove(H,T,Res,false);
member_remove(H,[V|T],Res,Bool) -> member_remove(H,T,[V|Res],Bool).

member_remove関数は、要素のすべてのオカレンスが重複しているかどうか、およびテスト結果がチェックされることなく、残りのテールを1回のパスで返します。

于 2013-03-13T20:56:34.247 に答える
3

私はこのようにするかもしれません:)

get_unique(L) ->
    SortedL = lists:sort(L),
    get_unique(SortedL, []).

get_unique([H | T], [H | Acc]) ->
    get_unique(T, [{dup, H} | Acc]);
get_unique([H | T], [{dup, H} | Acc]) ->
    get_unique(T, [{dup, H} | Acc]);
get_unique([H | T], [{dup, _} | Acc]) ->
    get_unique(T, [H | Acc]);
get_unique([H | T], Acc) ->
    get_unique(T, [H | Acc]);
get_unique([], [{dup, _} | Acc]) ->
    Acc;
get_unique([], Acc) ->
    Acc.
于 2013-03-14T09:40:32.257 に答える
1

2つのアキュムレータを使用します。1つはこれまでに見た要素を保持するためのもので、もう1つは実際の結果を保持するためのものです。アイテムを初めて表示する場合(表示リストにはない)、両方のリストの前にアイテムを追加して繰り返します。以前にアイテムを見たことがある場合は、繰り返す前に結果リスト(Acc)からアイテムを削除してください。

-module(test).

-export([uniques/1]).

uniques(L) ->
    uniques(L, [], []).

uniques([], _, Acc) ->
    lists:reverse(Acc);
uniques([X | Rest], Seen, Acc) ->
    case lists:member(X, Seen) of
        true -> uniques(Rest, Seen, lists:delete(X, Acc));
        false -> uniques(Rest, [X | Seen], [X | Acc])
    end.
于 2013-03-13T19:24:12.547 に答える
1

私は考えがあるかもしれないと思います:あなたがすでにリストの頭を見たかどうかをチェックしてください。その場合は、それをスキップして、テールを再帰的にチェックします。そうでない場合は、現在のヘッドを結果に追加し、「表示」して、テールを再帰的にチェックします。アイテムが設定されていることをすでに確認したかどうかを確認するための最も適切な構造。

だから、私は次のことを提案します:

 remove_duplicates(L) -> remove_duplicates(L,[], sets:new()). 

  remove_duplicates([],Result,_) -> Result;
  remove_duplicates([Head|Tail],Result, Seen) ->
    case sets:is_element(Head,Seen) of
      true -> remove_duplicates(Tail,Result,Seen);
      false -> remove_duplicates(Tail,[Head|Result], sets:add_element(Head,Seen))
    end.
于 2013-03-14T18:24:25.307 に答える
1
unique(List) ->
    Set = sets:from_list(List),
    sets:to_list(Set).
于 2017-10-03T10:49:08.850 に答える
0

次のコードを試してください

-module(util).

-export([unique_list/1]).

unique_list([]) -> [];
unique_list(L)  -> unique_list(L, []).

% Base Case
unique_list([], Acc) -> 
    lists:reverse(Acc);

% Recursive Part 
unique_list([H|T], Acc) ->
    case lists:any(fun(X) -> X == H end, T) of
        true  -> 
            unique_list(lists:delete(H,T), Acc);
        false -> 
            unique_list(T, [H|Acc])
end.
于 2013-03-15T00:31:32.077 に答える
0

このソリューションは、リストから重複を除外するだけです。おそらく、あなたが望むことを実行するために構築する必要があります。

remove_duplicates(List)->
    lists:reverse(removing(List、[]))。

remove([]、This)-> This;
削除([A |テール]、Acc)->
    remove(delete_all(A、Tail)、[A | Acc])。

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(_、[])->[]。

編集


MicrosoftWindows[バージョン6.1.7601]
Copyright(c)2009MicrosoftCorporation。全著作権所有。

C:\ Windows \ System32> erl
Eshell V5.9(^ Gで中止)
1>リスト=[1,2,3,4、a、b、e、r、a、b、v、3,2,1、g、{red、green}、d、2,5,6,1 、4,6,5、{赤、緑}]。
[1,2,3,4、a、b、e、r、a、b、v、3,2,1、g、
 {赤、緑}、
 d、2、5、6、1、4、6、5、
 {赤、緑}]
2> remove_duplicates(List)。
[1,2,3,4、a、b、e、r、v、g、{red、green}、d、5,6]
3>

于 2013-03-13T20:13:52.427 に答える
0

unique(L)-> sets:to_list(sets:from_list(L))。

于 2017-03-02T14:30:13.807 に答える
-1

最も簡単な方法は、すでに持っている要素を追跡する「アキュムレータ」を備えた関数を使用することです。したがって、次のような関数を記述します

%unique_acc(Accumulator、List_to_take_from)。

アキュムレータバージョンをエクスポートせず、代わりにその呼び出し元をエクスポートすることで、クリーンな関数を使用できます。

-module(uniqueness).
-export([unique/1]).

unique(List) ->
    unique_acc([], List).

取得するリストが空の場合は、これで完了です。

unique_acc(Accumulator, []) ->
    Accumulator;

そうでない場合:

unique_acc(Accumulator, [X|Xs]) ->
   case lists:member(X, Accumulator) of
       true  -> unique_acc(Accumulator, Xs);
       false -> unique_acc([X|Accumulator], Xs)
   end.

注意すべき2つのこと:
-これリストBIFを使用します- lists:member/2。ただし、これは自分で簡単に書くことができます。
-要素の順序が逆になり、元のリストから結果になります。これが気に入らない場合は、unique/1として定義できますlists:reverse(unique_acc([], List))。またはさらに良いことに、自分で逆関数を書いてください!(それは簡単です)。

于 2013-03-13T18:55:15.210 に答える