Erlang实战建立文本索引

为文本建立索引是文本信息处理的一个重要的任务,给定一个由英文单词构成的文件,为文件中所有单词建立索引,记录每个单词出现的行号和每行出现的次数,并将索引存入一个文件。在Erlang实战练习(六)中我强调了当时建立文本索引的时候太粗糙,一是使用了尽量规避的进程字典的方式;二是分词使用的是正则表达式,不够灵活。本文将改进我以前建立文本索引的方式,使用ETS来存储单词及其索引列表,同时拆分词使用Erlang提供的string:token模块,更加灵活和可移植性。

word_index.erl文件的总体结构如下:

 
 
 
  1. -module(word_index).  
  2. -export([start/2]).  
  3. -import(re, [run/2,replace/4]).  
  4. -import(string,[substr/3]). 
  5. %% start两个参数:FileIn表示要建立索引的文本文件,FileOut表示索引保存的目标文件start(FileIn,FileOut) ->
  6.     {_First,Second} = file:open(FileIn,read),%% 只读打开FileIn文件   
  7. if
  8.         _First =:= ok ->
  9.             LineList = readFile(Second,0),%% 函数readFile/2的功能是将文本以行为单位,存入列表                
  10. %io:format("~nfile contents:~p~n",[LineList]),
  11.             TableID = ets:new(index,[ordered_set]),%% ets:new创建一个“键值”搜索表,
  12. 存储键值映射元祖,设置表名为index,表的类型为ordered_set                
  13. index(FileOut,LineList,TableID);%% 为文本中的每一行建立单词索引              
  14. _First =/= ok ->
  15.             io:format("Open file error: file doesn't exist!")
  16.     end.

readFile/2函数代码如下:

 
 
 
  1. %% 读取文本每一行,以{Line,LineNo}为元组存入列表中readFile(S, LineNo) -> readFile(S,LineNo,[]).
  2. readFile(S, LineNo, Ret) ->
  3.     UpdateLineNo = LineNo +1,
  4.     OneLine = io:get_line(S,''),%% 读取文件中的一行内容      if
  5.         OneLine =:= eof ->
  6.              io:format("Read file EOF!"),
  7.              file:close(S),
  8.              lists:reverse(Ret);
  9.         OneLine =/= eof ->
  10.             readFile(S,UpdateLineNo, [{OneLine,UpdateLineNo} | Ret])
  11.     end.

index/3函数代码如下:

 
 
 
  1. index(File,LineList,TableID) ->
  2.     if
  3.         length(LineList) =:= 0 ->
  4.             ToList = ets:tab2list(TableID),
  5.             io:format("index is:~n~p~n",[ToList]),
  6.             writeToFile(File,ToList),
  7.             io:format("create index success! ");
  8.         length(LineList) =/= 0 ->
  9.             First = lists:nth(1,LineList),
  10.             processOneLine(First,TableID),
  11.             index(File,lists:delete(First, LineList), TableID)            
  12.     end.
  13. %% 处理一行文本processOneLine(OneLine, TableID) ->
  14.     {Element, LineNo } = OneLine,
  15.     %io:format("Line no:~p~n",[LineNo]),
  16.     Words = string:tokens(Element,"\n\t "),
  17.     matchWords(Words,LineNo,TableID).
  18. matchWords([], LineNo, TableID) -> 
  19.     io:format("process line(~p) success!~n",[LineNo]);
  20.     
  21. matchWords(Words, LineNo, TableID) ->
  22.     %io:format("Words:~p~n",[Words]),
  23.     Word = lists:nth(1,Words),
  24.     _Value = ets:lookup(TableID,Word),%%返回值为匹配Word的元组列表       if
  25.         length(_Value) =:= 0 -> %% Word还未被索引,直接插入此Word索引                ets:insert(TableID,{Word,[{LineNo,1}]} );
  26.         length(_Value) =/= 0 -> %% Word已被索引,更新Word索引列表                 KVs = lists:nth(1,_Value),
  27.             Value = element(2,KVs),
  28.             ets:insert(TableID,{Word, insertRec(Value,LineNo) } )
  29.     end,
  30.     matchWords(lists:delete(Word, Words), LineNo, TableID).
  31. %% 处理行号与出现次数元组列表insertRec(List,LineNo) -> insertRec(List,LineNo,length(List)).
  32. insertRec(List, LineNo, 0) -> 
  33.     [{LineNo, 1} |List];
  34. insertRec(List, LineNo, Ret) ->
  35.     First = lists:nth(Ret,List),
  36.     {LN, Num} = First,
  37.     if
  38.         LN =:= LineNo ->
  39.             Temp = lists:delete(First, List),
  40.             [{LineNo, Num+1} | Temp];
  41.         LN =/= LineNo ->
  42.             insertRec(List, LineNo, Ret-1)
  43.     end.
  44.            
  45. %% 将索引写入文件writeToFile(File,ToList) ->
  46.     {ok,S} = file:open(File,write),
  47.     lists:foreach(fun(X) -> io:format(S,"~p.~n",[X]) end, ToList),
  48.     file:close(S).

至此,我已经将使用ets存储键值大型表来存储单词索引列表的程序讲完了,大家自己回去动手试验吧。本文是继续上文的一个续篇,是一种改进的建立文本索引方式。以后我还好继续通过实战练习来探讨Erlang的学习与总结思考,谢谢大家的关注。

原文:http://www.cnblogs.com/itfreer/archive/2012/05/07/Erlang_in_practise_index.html

网页名称:Erlang实战建立文本索引
链接分享:http://www.shufengxianlan.com/qtweb/news33/416533.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联