我应该收集角色的频率。
freq(Sample) -> freq(Sample,[]).
freq([],Freq) ->
Freq;
freq([Char|Rest],Freq)->
freq(Rest,[{Char,1}|Freq]).
此功能无法正常工作。如果输入是“foo”,那么输出将是 [{F,1},{0,1},{0,1}]。 但我希望输出像 [{F,1},{O,2}]。 我无法设法修改tulpe中的元素。任何人都可以帮我解决这个问题,并告诉我如何修复它?
答案 0 :(得分:3)
一线解决方案:o)
% 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}]
使用短列表非常快,但执行时间随着长列表的增加而增加(在我的PC上,对于1 000 000个字符文本,它需要6.5秒)。
相比之下,使用相同的1 000 000字符文本,里卡多解决方案需要5秒
我将尝试使用ets的另一个版本。
答案 1 :(得分:3)
到目前为止,最简单的方法是使用orddict
来存储已经附带update_counter
函数的值,并在(已排序)列表中返回值。
freq(Text) ->
lists:foldl(fun (C, D) -> orddict:update_counter(C, 1, D) end, orddict:new(), Text).
答案 2 :(得分:1)
尝试这样的事情:
freq(Text) ->
CharsDictionary = lists:foldl(fun(Char, Acc) -> dict:update_counter(Char, 1, Acc) end, dict:new(), Text),
dict:fold(fun(Char, Frequency, Acc) -> [{Char, Frequency} | Acc] end, [], CharsDictionary).
第一行创建一个字典,该字典使用char作为键,频率作为值(dict:update_counter)。
第二行转换您需要的列表中的字典。
答案 3 :(得分:1)
使用模式匹配和支持者。
-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.
测试
1> freq:char_freq("abacabz").
[{"z",1},{"b",2},{"a",3},{"c",1}]
答案 4 :(得分: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).