2016-12-22 7 views
1

タプルの最初の要素が別のリストの要素と一致するかどうかに基づいて、タプルのリストをフィルタリングしようとしています。Erlangでリスト内包の複数(タプルベース)ジェネレータ

たとえば、元のリストは

163>Shoppinglist. 
[{oranges,2},{milk,1},{apples,2}] 

私は<-表記で複数の発電機を使用しようとすると、それがループして要素の結果は、一度このようなより多くの繰り返しです:

164> [(Item)||{Item,Unit}<-Shoppinglist, Item<-[apples,milk]]. 
[apples,milk,apples,milk,apples,milk] 

これは、この質問のAlexey Romanovの答えでうまく説明されています:Multiple filters in list comprehension in Erlang。この回答に基づいて、私は以下を行うことができ、それは正常に動作します。

165>[{Item}||{Item,Unit}<-Shoppinglist,(Item==apples) or (Item==milk)]. 
[apples, milk] 

しかし、私は、入力として来て第二のリストItem<-[apples,milk]をしたいと思いますので、これは本当に、私のニーズを満たしていない、そして常に手動のため(Item==apples) or (Item==milk)のようなすべてのマッチを一覧表示するのは実用的ではないかもしれないので、非常に長いリスト。

実際に発電機として複数のリストを使用する方法はありますか?または私の問題を解決するより巧妙な方法。私はまだ非常にErlang(Pragmatic ProgrammingとLYSEの本を持つ)で始まったので、私はまだほとんど知りません。

+0

質問を書いた直後に、2番目のリストをタプルのリストに変換して、ただ1つのジェネレータを使うことができました。 | {Item、_Unit} < - [{apples、0}、{milk、0}]]。これは私がまだ知らない新しいことを紹介し、さらに学習曲線を上げています。http://stackoverflow.com/questions/5214821/list-to-tuples-convertionとhttp://stackoverflow.com/questions/3936613/erlang-prepending-an-element-to-a-tuple – Yogesch

答えて

3
1> Shoppinglist = [{oranges,2},{milk,1},{apples,2}]. 
[{oranges,2},{milk,1},{apples,2}] 
2> Filterlist = [apples,milk]. 
[apples,milk] 

最初の方法では、リストを直接フィルタリングします。リストの理解では、フィルタはfalseまたはtrueを返す任意の文です。メモリフットプリントに適していて、フィルタリストが大きい場合には出力時間が悪い。

3> [Item || {Item,_} <- Shoppinglist, lists:member(Item,Filterlist)]. 
[milk,apples] 

第2の方法では、クロス積とフィルタを生成します。クロス製品は、{{{オレンジ、2}、リンゴ}、{{ミルク、1}、リンゴ}、{{リンゴ、2}、リンゴ}、{{オレンジ、2}、ミルク}、{{ミルク、 1}、ミルク}、{{リンゴ、2}、ミルク}]、私はそれが実際にビルドされているとは思わないが、フィルタの仕組みを理解するのに役立ちます。メモリフットプリントには悪く、パフォーマンスには疑問符。

4> [Item1 || {Item1,_} <- Shoppinglist, Item2 <- Filterlist, Item1 == Item2]. 
[milk,apples] 

リストは大きな可能性がある場合、私は最初のソリューションが優れていることを考えると、コードは(ビッグリスト、多くのコール)重大であるならば、私はフィルタリストからマップを作成することをお勧めしてから使用しますフィルタとしてのこのマップ:

5> [Item || {Item,_} <- Shoppinglist, maps:get(Item,lists:foldl(fun(X,Acc) -> maps:put(X,true,Acc) end, #{},Filterlist),false)]. 
[milk,apples] 
2

私の意見では、リストの理解はこのタスクの適切なツールではありません。私はむしろセットを作成し、交差点を見つけることを好むでしょう:

SList = [{oranges,2},{milk,1},{apples,2}]. 
IList = [apples, milk]. 
ISet = sets:from_list(IList). 
SSet = sets:from_list([I|{I,_} <- SList]). 
6> sets:to_list(sets:intersection(ISet, SSet)). 
[apples,milk] 
+0

セットへの変換と通常の設定交差を行う非常に面白いアプローチですが、他の問題にも役立つと思います... – Yogesch