Erlang 一种简单的二郎捻线机
我在玩erlang中的列表。我有以下格式的随机填充列表:Erlang 一种简单的二郎捻线机,erlang,erlang-shell,Erlang,Erlang Shell,我在玩erlang中的列表。我有以下格式的随机填充列表: List=[{10,"English",id1},{20,"Maths",id2},{30,"Geo",id3},{20,"English",id4}] 它的格式为[{Marks,Subject,Id}] 我想从这个列表中列出一个只包含“英语”作为主题的列表,我做了如下操作 NewList=List:filter(乐趣(A)->element(2,A)=“English”,List) 这让我 [{10,"English",id1},{2
List=[{10,"English",id1},{20,"Maths",id2},{30,"Geo",id3},{20,"English",id4}]
它的格式为[{Marks,Subject,Id}]
我想从这个列表中列出一个只包含“英语”作为主题的列表,我做了如下操作
NewList=List:filter(乐趣(A)->element(2,A)=“English”,List)
这让我
[{10,"English",id1},{20,"English",id4}]
这很好,但是现在我想得到NewList中元组的id,它有更大的标记值,例如,这里
在id1
和id4
中,由于id4更大,我需要id4
这里的问题是,列表是随机填充的列表,这意味着将来可能会出现所有4个条目,其主题仅为英语
有人能提出一个解决办法吗?提前谢谢。在筛选完列表后,您不能使用
lists:max/1
来获取具有最大标记的元组吗
lists:max(NewList)
如果我理解正确,那就行了:
NewList = lists:filter(fun(A)->element(2,A)=="English" end,List).
{_, _, MaxID} = lists:max(NewList).
注意,这假设输入列表只包含所需主题的元组,因为OP已经对其进行了过滤。或者,可以在此处添加过滤器,以避免单独的步骤 要获取具有每个元素的任意元素的最大值的元组(在本例中,标记可以是多个具有相同标记的元组),而不考虑元组排序规则,可以执行类似的操作(使用第一个元素进行比较,如本问题所述),只要列表至少包含一个元素 使用包含第一个列表项和该项的标记值的元组作为初始累加器。然后,从第二个元组开始,如果所讨论的输入元组具有等于当前最高值的标记,则将其添加到累加器的列表中。如果当前输入元组的标记高于当前最高值,请将累加器中的列表替换为仅包含当前输入元组的新列表。否则,保持蓄能器不变。如果列表仅包含一个条目,则将返回该条目,因为它是
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>
我认为德里克·布朗的解决方案行不通<代码>列表:foldl()允许您在维护和操作单独变量的同时单步浏览列表。处理完最后一个元素后,
列出: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
).
在您的情况下,单独的变量将包含迄今为止得分最高的学生
在外壳中:
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()
遍历列表一次,然后使用max()
遍历第二次。你可以想象,如果你有一个包含数百万个元素的列表,你应该尽可能少地遍历该列表。1>list=[{10,“math”,“Joe”}、{12,“english”,“Mark”}、{10,“math”,“Rebecca”}、{15,“english”,“Janice”}]。
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>
[{10,“数学”,“乔”},
{12,“英语”,“马克”},
{10,“数学”,“丽贝卡”},
{15,“英语”,“珍妮丝”}]
2> Best=fun(List,Subject)->List:foldl(fun({Mark,S,Id},{BestMark,})当Mark>BestMark,S==Subject->{Mark,[Id]};
2> ({Mark,S,Id},{BestMark,Students})当Mark==BestMark,S==Subject->{BestMark,[Id | Students]};
2> (u,Acc)->Acc
2> 结束,{0,[]},列表)结束。
#乐趣
3> 最佳(列出“数学”)。
{10,[“丽贝卡”,“乔”]}
4> 最佳(列表“英语”)。
{15,[“Janice”]}
5> 最佳(列表,“艺术”)。
{0,[]}
6>
lists:max/1将为我提供最高分数,但我想获取获得最高分数的人的Idlists:max
将为您提供整个元组。我在整个列表上尝试了lists:max
(没有过滤),它返回:{30,“Geo”,id3}
是的,你是对的,lists:max/1获取元组的第一个元素并使用它来查找最大值。我尝试将元组的更改顺序设置为[{subject,marks,id}],以数学为主题的元组为最大值。@abhishekranjan:No,lists:max/1
不取元组的第一个元素并使用它来查找最大值。看见例如list:sort([{1,b,2},{1,a,2},{1,d}])。
元组按大小排序,两个大小相同的元组按元素进行比较。明白了,list:max/1取元组中的第一个元素进行比较。编辑我的答案以说明多个具有相同标记的条目-很好。@DerekBrown,op希望根据主题选择最高分数,而不是总体最高分数。一个连锁反应是,你不能使用列表中的第一个元素作为初始Acc值,因为它可能不是正确的主题。我知道,但OP已经过滤了所需主题,正如我在编辑答案的第一段中提到的。或者,可以使用原始列表并在代码中添加该检查,就像您所做的那样,然后可以使用atom undefined的初始累加器或其他一些标志值,并添加一个fun子句accoun