我有以下列表項目 [{id, user1, category1}, {id, user2, category1}, {id, user1, category2}....],
其中id是唯一的,並且用戶/類別可以重複。我正試圖弄清楚如何從列表中獲取統計信息,例如erlang:元組列表中的項目
[{user1, category1, 20}, {user1, category2, 30}..]
我有以下列表項目 [{id, user1, category1}, {id, user2, category1}, {id, user1, category2}....],
其中id是唯一的,並且用戶/類別可以重複。我正試圖弄清楚如何從列表中獲取統計信息,例如erlang:元組列表中的項目
[{user1, category1, 20}, {user1, category2, 30}..]
您可以使用列表做到這一點:與foldl/3的功能。
F = fun({_,User,Cat},Accumulator) ->
N = maps:get({User,Cat},Accumulator,0),
maps:put({User,Cat},N+1,Accumulator) end.
CountMap = lists:foldl(F,#{},InputListe),
這將返回地圖的形式#{{user1, category1} => 20, {user1, category2} => 30 ...}
的,如果你真的需要一個名單,那麼你必須改變地圖:
CountList = maps:fold(fun({User,Cat}, Count, Acc) -> [{User,Cat,Count}|Acc] end,[],CountMap).
我用一箇中介地圖,因爲如果輸入列表很大,然後它可以快速訪問和快速更新,與直接在輸出列表中工作的解決方案相比較。檢索列表中的信息(平均分析列表的一半)花費很多,並且修改它也花費很多(平均複製一半列表
對於200,000個元素的輸入列表,它需要94毫秒來生成地圖並將其轉換成我的筆記本電腦上的列表,併爲219萬500000元素。
儘管Pascal'ssolution是一個很好的通用解決方案,對於小數據集(如高達15 000),您可以使用這個版本使用lists:sort/1
,這對他們來說顯着更快。
main(L) ->
count(lists:sort(transform(L))).
count([]) -> [];
count([H|T]) ->
count(H, T, 1, []).
count(H, [H|T], N, Acc) -> count(H, T, N+1, Acc);
count({U, C}, [H|T], N, Acc) -> count(H, T, 1, [{U, C, N}|Acc]);
count({U, C}, [], N, Acc) -> [{U, C, N}|Acc].
transform(L) ->
transform(L, []).
transform([], Acc) -> Acc;
transform([{_, User, Category}|T], Acc) ->
transform(T, [{User, Category}|Acc]).
編輯:
確定哪種算法更快的關鍵點是唯一鍵的比例。如果存在大數據集但具有少量獨特的地圖,則使用地圖的解決方案將更快。如果相反,lists:sort/1
會更快。換句話說,列表與地圖的大小關係重大。
:o)它提醒了我一些事情 – Pascal