我正在玩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值,例如,
id1
和id4
,因为id4更大,我需要Id4。
这里的问题是List是随机填充的列表,这意味着将来所有4个条目都可能存在,其主题仅为英语
任何人都可以建议出路。谢谢。
答案 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>