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

时间:2013-11-19 11:00:22

标签: erlang tuples

我应该收集角色的频率。

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中的元素。任何人都可以帮我解决这个问题,并告诉我如何修复它?

5 个答案:

答案 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).