2017-10-06 11 views
1

リストbから見つかった要素をリストaから削除します。 このコードの実行後、リストaは[1,2,3,4]を印刷しています。エリクサーは2つのリストから共通の要素を削除します

Enum.filter(a, fn el -> !Enum.member?(b, el) end) 

出力:

defmodule Test do 
def listing do 
    a = [1,2,3,4] 
    b = [3,4,5,6] 

    Enum.each b, fn elemB -> 
     a = Enum.filter(a, fn(x) -> x != elemB == true end) 
     #IO.inspect a 
    end 
    IO.inspect a 
end 
end 

Test.listing() 

答えて

2

あなたは外Enum.eachが、あなたはそれがbのメンバーであるかどうかを確認するために、各要素をaの上に列挙してチェックすることによって、単一のフィルタでそれを行うことができます必要はありません。 :

[1, 2] 

それはあなたがaを変更しようとしているあなたの現在のソリューションと同じように見えますが、それはエリクサーので動作しません機能的であり、機能は副作用を有することができない。 eachaは元のリストであるaと同じではありません。

3

どちらの方法を使用することができます。しかし、リストは大きく、非常に非効率的です。

リストはMapSetを使用して、大規模な優れている場合:

MapSet.difference(MapSet.new(a), MapSet.new(b)) |> MapSet.to_list 

しばらくEnum.filter、それはMapSetsのに両方のリストを変換するためにいくつかの時間を費やし、再びリストに結果を変換するために、これらの操作はn log(n)であり、ここでの減算(--)は2次です。

私はgist with benchmarksを準備しました。

要約:非常に短いリストの減算が最も速く、約100要素の長さのリストの場合はEnum.filterが最速であり、1000要素のリストの場合はMapSet.differenceが最も高速です。 100K要素のリストで数百倍も高速です。

実際には、このサイズのリストは、MapSet.differenceは0.08秒、Enum.filterは16秒、減算は44秒です。

UPDATEDogbertは私に尋ねたにもベンチマークのErlangのordsets:それは特にミッドサイズに、より速くMapSetよりも動作します

:ordsets.subtract(:ordsets.from_list(a), :ordsets.from_list(b)) |> :ordsets.to_list 

MapSet1.4倍遅い)長さ約1000個のレコードを示しています。

+0

ベンチマークに向かって? Erlangのドキュメントでは '--'の代わりにそれを使うことを推奨しています。 ':ordsets.subtract(:ordsets.from_list(a)、:ordsets.from_list(b))|>:ordsets.to_list'である。 – Dogbert

+1

また、リストからマップセットへの変換は線形ではなく、ErlangのMapに値を挿入するとO(log n)なので、O(n log n)です。 – Dogbert

+1

@Dogbert、私はそれをしました、結果を確認してください。 –

0

あなたが代わりにEnum.filterEnum.rejectを使用してコードをより明確にすることができます@Tylerの答えは、
するには、次

Enum.reject(a, fn el -> Enum.member?(b, el) end)  

これは、同じ結果が得られます: `あなたも追加することができます

Enum.filter(a, fn el -> !Enum.member?(b, el) end) 
関連する問題