2012-06-16 3 views
1

Учитывая файл журнала .txt, который находится в форме:Как подсчет уникальных пользователей в журнале файлов?

USER_A timestamp1 otherstuff 
USER_B timestamp2 otherstuff 
USER_C timestamp3 otherstuff 
USER_A timestamp4 otherstuff 
USER_A timestamp5 otherstuff 
USER_C timestamp6 otherstuff 
USER_B timestamp7 otherstuff 

Как посчитать количество различных уникальных пользователей в Erlang? Я думал о том, чтобы читать файл по строкам и использовать модуль proplists. Каждый пользователь будет ключевым, со значением, которое будет числом вхождений. Как только файл будет прочитан, я звоню:

length(proplists:get_keys(List)). 

Это правильный способ достичь моего результата?

ответ

4

Я бы также использовал для этого набор модулей, так как он является быстрым и в качестве набора не содержит дубликатов.

Следующий код должен делать эту работу:

{ok,Bin} = file:read_file("test"), 
List = binary_to_list(Bin), 
Usernames = [hd(string:tokens(X," ")) || X <- string:tokens(List,[$\n])], 
sets:size(sets:from_list(Usernames)). 

Edit: я удалил одну гильзы, так как он не добавляет никакого ценности

+2

Обратите внимание, что это будет содержать весь файл в памяти. Может быть лучше с точки зрения памяти читать одну строку за раз из файла и добавлять имя пользователя в набор, например, в рекурсивной функции. –

+0

Да, конечно, это хороший момент –

3

Возможно, было бы более целесообразно использовать набор из модуля sets для хранения имен пользователей, а затем использовать sets:size/1.

1

файлов журналы часто большие, рассмотреть возможность работы с ним один построчно в рекурсивной функции:

% Count the number of distinct users in the file named Filename       
count_users(Filename) -> 
    {ok, File} = file:open(Filename, [read, raw, read_ahead]), 
    Usernames = usernames(File, sets:new()), 
    file:close(File), 
    sets:size(Usernames). 

% Add all users in File, from the current file pointer position and forward, 
% to Set. 
% Side-effects: File is read and the file pointer is moved to the end.   
usernames(File, Set) -> 
    case file:read_line(File) of 
     {ok, Line} -> 
      Username = hd(string:tokens(Line, " ")), 
      usernames(File, sets:add_element(Username, Set)); 
     eof -> 
      Set 
    end. 

Вы просто назвать его так: count_users("logfile").

Обратите внимание, что usernames/2 должно быть tail recursive для того, чтобы это эффективно работало. В противном случае он просто потреблял бы еще больше памяти.

Смежные вопросы