2017-06-19 6 views
1

私はerlangのリストで遊んでいました。私は次のフォーマットのランダムに人口が多いリストを持っています:シンプルなErlangツイスター

List=[{10,"English",id1},{20,"Maths",id2},{30,"Geo",id3},{20,"English",id4}] 

これは[{マーク、件名、ID}の形式です。

私は私の罰金です

[{10,"English",id1},{20,"English",id4}] 

を与える

NewList=lists:filter(fun(A)->element(2,A)=="English",List)

を次のように私がした対象としてだけで「英語」を含有する、このリストからリストを作りたかった

しかし今、私はタプルのIDをNewListの中に入れたいと思っています。例えば、マークの値が大きいNewListの場合は

id4が大きいのでf id1id4のため、Id4が必要です。

ここでの問題は、そのリストは、将来的にすべての4つのエントリがその対象となり、英語のみ

誰もが事前に通行out.Thanksを提案することができます存在してもよいことを意味し、ランダムに取り込まリストです。

答えて

1

リストをフィルタリングしたあと、lists:max/1を使用して最大のタプルを取得できませんでしたか?

lists:max(NewList) 
+0

リスト:最大/ 1は私の最大のマークを与えるだろうが、私は最大のマーク –

+0

'リストを有する者のIDを取得したい:max'はあなたの全体のタプルを与えるだろう。私はリスト全体(フィルタリングなし)で 'lists:max'を試してみました。' {30、 "Geo"、id3} ' –

+0

はい、あなたは正しかった、リスト:max/1はタプルの最初の要素をとり、それを使って最大値を求めます。{{subject、marks、id}]のようにタプルの順番を変更してみましたが、最大数として数学でタプルを得ました。 –

1

私が正しく理解している場合、動作します:

NewList = lists:filter(fun(A)->element(2,A)=="English" end,List). 
{_, _, MaxID} = lists:max(NewList). 
+0

、リスト:max/1は、タプル内の比較のための最初の要素をとります。 –

0

注これは、入力リストは、OPがすでにその上で濾過しているようにのみ、所望の被写体のためにタプル含まれていることを前提としていること。あるいは、別のステップを避けるためにここにフィルタを追加することもできます。

タプルの順序付けルールを気にすることなく、それぞれの任意の要素の最大値を持つタプルを取得するには(このマークは複数の場合があります)、次のようにします(この質問のように、最初の要素を比較のために使用します)、リストに少なくとも1つの要素が含まれている限りです。

初期アキュムレータとして、最初のリストエントリとそのエントリのマークの値を含むタプルを使用します。次に、2番目のタプルから始めて、問題の入力タプルに現在の最高のマークがある場合は、アキュムレータのリストに追加します。現在の入力タプルに現在の最高値よりも高いマークがある場合は、アキュムレータのリストを現在の入力タプルのみを含む新しいリストに置き換えます。さもなければ、アキュムレーターをそのまま保管してください。リストに1つのエントリのみが含まれている場合は、foldlコールの最初のアキュムレータであるため、そのエントリが返されます。

find_max([{FirstMarks, _, _} = First | T]) -> 
    lists:foldl(
    fun 
     %% Current tuple from input list has marks higher than current highest in accumulator, 
     %% so reset the accumulator to this new value for marks and new list containing 
     %% just this input list tuple 
     ({N, _, _} = This, {MaxN, _L}) when N > MaxN -> 
     {N, [This]}; 
     %% Current tuple from input list has marks equal to current highest in accumulator, 
     %% so add this input list tuple to the accumulator's list 
     ({N, _, _} = This, {N, L}) -> 
     {N, [This | L]}; 
     %% Current tuple from input list has marks less than current highest in accumulator, 
     %% so don't change accumulator 
     (_, Acc) -> 
     Acc 
    end, 
    %% Accumulator is tuple containing initial high value for marks, and list containing 
    %% containing the first element of the input list 
    {FirstMarks, [First]}, T). 

1> tst_so:find_max([{30, a, a}]). 
{30,[{30,a,a}]} 
2> 
2> tst_so:find_max([{30, a, a}, {20, b, b}, {40, c, c}, {10, d, d}, {40, e, e}]). 
{40,[{40,e,e},{40,c,c}]} 
3> 
1

デレク・ブラウンのlists:foldl()ソリューションは正しく動作しません。 lists:foldl()を使用すると、別の変数を維持して操作しながらリストをステップ実行できます。最後の要素が処理された後、lists:foldl()は別の変数を返します。この場合、個別の変数を使用して、最高のマークでスチューデントを更新することができます。

あなたは、引数がリストの現在の要素であり、操作する別の変数であるfunをlists:foldl()に提供します。funの戻り値は、別の変数の新しい値です。

あなたのケースでは、別の変数はこれまでのところ最高のマークを持つ学生を保持します。シェルで

50> c(my).       
{ok,my} 

51> Students = [{10,"English",id1},{20,"Maths",id2},{30,"Geo",id3},{30,"Maths",id1},{30,"English",id4},{20,"English",id3}]. 
[{10,"English",id1}, 
{20,"Maths",id2}, 
{30,"Geo",id3}, 
{30,"Maths",id1}, 
{30,"English",id4}, 
{20,"English",id3}] 

52> my:max_mark(Students, "English").                      
{30,"English",id4} 

53> my:max_mark(Students, "Maths").                       
{30,"Maths",id1} 

54> my:max_mark(Students, "Geo").                       
{30,"Geo",id3} 

取得絆はいくつかのより多くの作業がかかります。

lists:foldl()を使用することの利点は、あなただけではなくfilter()と、リスト1つの時間を横断するよりも、必要な情報を取得し、max()と、その後二度目ために一度あなたのリストをトラバースしなければならないということです。数百万の要素を持つリストがあれば、可能な限り数回リストをたどるようにすることができます。

+0

同じマークを持つ複数のエントリーを考慮して私の答えを編集しました - 良い点。 –

+0

@DerekBrown、opは、全体的に最高のスコアではなく、主題に基づいて最高のスコアを選択したいと考えています。効果のノックは、正しい主題ではない可能性があるため、リストの最初の要素を最初のAcc値として使用できないことです。 – 7stud

+0

私は知っていますが、私は編集した答えの最初の段落で言及しているように、OPはすでに目的のSubjectでフィルタリングされています。また、未処理のリストを使用してコード内にそのチェックを追加して、未定義アトムの初期アキュムレータやその他のフラグ値を使用し、その可能性を考慮したfun句を追加することもできます(現在のSubjectは希望の値、accはフラグ値、{N、[This]}の新しいアキュムレータを返します(変数名を使用します))。 –

0
1> List = [{10,"maths", "Joe"},{12,"english","Mark"},{10,"maths","Rebecca"},{15,"english","Janice"}]. 
[{10,"maths","Joe"}, 
{12,"english","Mark"}, 
{10,"maths","Rebecca"}, 
{15,"english","Janice"}] 
2> Best = fun(List,Subject) -> lists:foldl(fun({Mark,S,Id},{BestMark,_}) when Mark > BestMark, S == Subject -> {Mark,[Id]};      
2>           ({Mark,S,Id},{BestMark,Students}) when Mark == BestMark, S == Subject -> {BestMark,[Id|Students]}; 
2>           (_,Acc) -> Acc                       
2>           end,{0,[]},List) end.                     
#Fun<erl_eval.12.52032458> 
3> Best(List,"maths").                                 
{10,["Rebecca","Joe"]} 
4> Best(List,"english").                                
{15,["Janice"]} 
5> Best(List,"art").  
{0,[]} 
6> 
関連する問題