主题:问一个统计词频的问题
zl001
[专家分:0] 发布于 2007-12-01 11:10:00
各位,我想问一下一个统计词频的问题.
就是要统计出,一个文本中每个单词的数量.
比如,文档里面是I AM A BOY , I AM A GIRL。
返回值要求是 I = 2 AM=2 A=2 BOY=1 GIRL=1。
问题是文档很大。全部文本就有29兆。
谢谢. 有delphi源码的那最好了.
回复列表 (共2个回复)
沙发
HongYi [专家分:0] 发布于 2007-12-04 16:09:00
建立链表,构建节点内容如下:
单词、单词的数量、后继指针域。
1.初始化链表,含表头节点,表头不存放有效数据,只是为了操作的方便。
2.从文本文件中读取单词。
3.将该单词与链表中的节点单词比较。假如相同,则单词数量增1,比较结束;否则继续跟后一节点单词比较,直到链表结尾。当比较至表尾时,则新增节点,并初始化之(节点单词赋当前单词,单词数量赋1...)。
4.继续读取单词、比较,直到文本结束。
5.遍历链表。按类似“I=2 AM=2 A=2 BOY=1 GIRL=1”的格式输出。
说明:从文本文件中读取单词时,考虑到单词间以空格为分隔符,应该如何定位至文本的当前读取位置,对于这一点我还没有好的方法。
板凳
HongYi [专家分:0] 发布于 2007-12-05 10:21:00
这里我用 TEdit模仿文本文件,输出结果显示在 TMemo中,程序代码如下。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TArr = array [1..20] of string; //保存从语句中读取的单词,最大20个,可修改大小
TCompartSymbols = set of Char; //记录单词间的分隔符号 比如当前的分隔符为[' ', ',']
PWord = ^TRecordWord;
TRecordWord = record
CurWord: string;
Number: Integer;
Next: PWord;
end;
TForm1 = class(TForm)
Edit1: TEdit;
btnOutput: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure btnOutputClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
ItsWord, HeadWord, LastWord: PWord; //HeadWord 头节点指针,LastWord 尾节点指针
procedure Compare(AStr: string); //将当前读取的单词与链表(保存已出现过的单词)中单词比较
function SubStr(AStr: string; Const Compart: TCompartSymbols; var Arr: TArr): Integer;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Compare(AStr: string);
begin
ItsWord := HeadWord.Next;
while ItsWord <> nil do
if ItsWord.CurWord <> AStr then
ItsWord := ItsWord.Next
else begin
ItsWord.Number := ItsWord.Number + 1;
Break;
end;
if ItsWord = nil then
begin
New(ItsWord);
ItsWord.CurWord := AStr;
ItsWord.Number := 1;
ItsWord.Next := nil;
LastWord.Next := ItsWord;
LastWord := ItsWord;
end;
end;
// 返回语句中单词的个数,Compart 表示单词间分隔符号集
function TForm1.SubStr(AStr: string; const Compart: TCompartSymbols; var Arr: TArr): Integer;
var
OriginPos, i: Integer;
begin
AStr := Trim(AStr); //删除AStr中的前导、尾随空格
OriginPos := 1;
Result := 0;
for i := 1 to Length(AStr) do
if AStr[i] in Compart then
begin
Result := Result + 1;
Arr[Result] := Copy(AStr, OriginPos, i - OriginPos);
OriginPos := i + 1;
end;
//保存最后的一个单词
Result := Result + 1;
Arr[Result] := Copy(AStr, OriginPos, i - OriginPos);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
//创建头节点并赋初值
New(ItsWord);
ItsWord.CurWord := '';
ItsWord.Number := 0;
ItsWord.Next := nil;
HeadWord := ItsWord;
LastWord := ItsWord;
end;
procedure TForm1.btnOutputClick(Sender: TObject);
var
Num, i: Integer;
TempArr: TArr;
begin
Num := SubStr(Edit1.Text, [' ', ','], TempArr);
for i := 1 to Num do
Compare(TempArr[i]);
Memo1.Lines.Clear;
ItsWord := HeadWord.Next;
while ItsWord <> nil do
begin
Memo1.Lines.Add(ItsWord.CurWord + ' = ' + IntToStr(ItsWord.Number));
ItsWord := ItsWord.Next;
end;
end;
end.
我来回复