如何使用Erlang中的元组列表{char,freq}收集字符频率

如何使用Erlang中的元组列表{char,freq}收集字符频率,erlang,tuples,Erlang,Tuples,我应该收集字符的频率 freq(Sample) -> freq(Sample,[]). freq([],Freq) -> Freq; freq([Char|Rest],Freq)-> freq(Rest,[{Char,1}|Freq]). 此函数的工作方式不正确。如果输入为“foo”,则输出为 [{f,1},{o,1},{o,1}]。 但我希望有这样的输出 [{f,1},{o,2}]。 我无法修改薄纱中的元素。有人能帮我解决这个问题,并告诉我如何修复它吗?试

我应该收集字符的频率

freq(Sample) -> freq(Sample,[]).

freq([],Freq) ->
    Freq;
freq([Char|Rest],Freq)->
    freq(Rest,[{Char,1}|Freq]).
此函数的工作方式不正确。如果输入为“foo”,则输出为 [{f,1},{o,1},{o,1}]。 但我希望有这样的输出 [{f,1},{o,2}]。
我无法修改薄纱中的元素。有人能帮我解决这个问题,并告诉我如何修复它吗?

试试这样的方法:

freq(文本)->
CharsDictionary=list:foldl(fun(Char,Acc)->dict:update_counter(Char,1,Acc)end,dict:new(),Text),
单词:fold(fun(Char,Frequency,Acc)->[{Char,Frequency}|Acc]end,[],CharsDictionary)。
第一行创建一个字典,使用char作为键,使用frequency作为值()


第二行使用模式匹配和PropList转换列表中所需的词典。

-module(freq).
-export([char_freq/1]).

-spec char_freq(string()) -> [tuple()].
char_freq(L) -> char_freq(L, []).

char_freq([], PL) -> PL;
char_freq([H|T], PL) ->
    case proplists:get_value([H], PL) of
        undefined ->
            char_freq(T, [{[H],1}|PL]);
        N ->
            L = proplists:delete([H], PL),
            char_freq(T, [{[H],N+1}|L])
    end.
试验

单线解决方案:o)

短列表的速度相当快,但长列表的执行时间增加了很多(在我的电脑上,1000个字符的文本需要6.5秒)

相比之下,对于相同的1000个字符的文本,Ricardo解决方案需要5秒

我将使用ets尝试另一个版本。

L=[list_to_atom(X)| X dict:update_counter(Char,1,Acc)end,dict:new(),L)。
L = [list_to_atom(X) || X <- Str].
D = lists:foldl(fun({Char, _}, Acc) -> dict:update_counter(Char, 1, Acc) end, dict:new(), L).
dict:to_list(D).
口述:给列表(D)。
到目前为止,最简单的方法是使用
orddict
存储值,因为它已经带有
update\u counter
函数,并在(排序)列表中返回值


查看一些灵感使用
或dict:update\u counter/3
。我已通过附加功能修复了该问题。 不过还是要谢谢你的帮助。+1@Pascal:哇!这是更好的模式匹配。我正在学习,谢谢你展示了更好的方法:)。
% generate a random list
L = [random:uniform(26)+$a-1 || _ <- lists:seq(1,1000)].

% collect frequency
lists:foldl(fun(X,[{[X],I}|Q]) -> [{[X],I+1}|Q] ; (X,Acc) -> [{[X],1}|Acc] end , [], lists:sort(L)).
1> lists:foldl(fun(X,[{[X],I}|Q]) -> [{[X],I+1}|Q] ; (X,Acc) -> [{[X],1}|Acc] end , [], lists:sort("foo")).
[{"o",2},{"f",1}]
L = [list_to_atom(X) || X <- Str].
D = lists:foldl(fun({Char, _}, Acc) -> dict:update_counter(Char, 1, Acc) end, dict:new(), L).
dict:to_list(D).
freq(Text) ->
    lists:foldl(fun (C, D) -> orddict:update_counter(C, 1, D) end, orddict:new(), Text).