一个简单的Erlang扭转者

时间:2017-06-19 12:58:19

标签: erlang erlang-shell

我正在玩erlang中的列表。我有一个随机填充的以下格式列表:

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

格式为[{Marks,Subject,Id}]。

我想从这个列表中列出一个仅包含“英语”的列表作为我所做的主题,如下所示

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

给了我

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

这很好,但现在我想得到NewList中元组的id,它具有更大的Marks值,例如,

id1id4,因为id4更大,我需要Id4。

这里的问题是List是随机填充的列表,这意味着将来所有4个条目都可能存在,其主题仅为英语

任何人都可以建议出路。谢谢。

5 个答案:

答案 0 :(得分:1)

过滤列表后,您是否不能使用lists:max/1来获取最大分数的元组?

lists:max(NewList)

答案 1 :(得分:1)

如果我理解正确,那就行了:

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

答案 2 :(得分:1)

我认为Derek Brown的lists:foldl()解决方案无法正常运行。 lists:foldl()允许您在维护和操作单独变量的同时单步执行列表。处理完最后一个元素后,lists:foldl()将返回单独的变量。在这种情况下,您可以使用单独的变量来更新具有最高分数的学生。

您为lists:foldl()提供了一个乐趣,其参数是列表中的当前元素以及您要操作的单独变量。 fun的返回值是单独变量的新值。

max_mark(Students, Subject) ->
    lists:foldl(
      fun({M,S,_Id}=Student, {Highest,_,_}) when S=:=Subject, M>Highest -> Student;
         (_Student, BestStudent) -> BestStudent
      end,
      {0, Subject, none},  %Starting value for the separate variable
      Students   %The list you want to step through
    ).

在您的情况下,单独的变量将保留目前为止具有最高分数的学生。

在shell中:

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}}。你可以想象,如果你有一个包含数百万个元素的列表,那么你应该尽可能多地遍历列表。

答案 3 :(得分:0)

请注意,这假设输入列表仅包含所需主题的元组,因为OP已经对其进行了过滤。或者,可以在此处添加过滤器以避免单独的步骤。

为了获得具有每个元素的任意元素的最大值的元组(在这种情况下标记,其中可以有多个具有相同标记的元素),而不考虑元组排序规则,可以执行类似这样的操作(只要列表包含至少一个元素,它就会使用第一个元素进行比较,如本问题所示。

使用包含第一个列表条目的Marks值的元组,并将该条目作为初始累加器。然后,从第二个元组开始,如果所讨论的输入元组的Marks等于当前最高值,则添加到累加器中的列表。如果当前输入元组的标记高于当前最高标记,则使用仅包含当前输入元组的新列表替换累加器中的列表。否则,按原样保持累加器。如果列表只包含一个条目,那么它将作为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>

答案 4 :(得分: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>