回 帖 发 新 帖 刷新版面

主题:问一个统计词频的问题

各位,我想问一下一个统计词频的问题.
就是要统计出,一个文本中每个单词的数量.
比如,文档里面是I AM A BOY , I AM A GIRL。
返回值要求是 I = 2 AM=2 A=2 BOY=1 GIRL=1。
问题是文档很大。全部文本就有29兆。
谢谢. 有delphi源码的那最好了.

回复列表 (共2个回复)

沙发

建立链表,构建节点内容如下:
  单词、单词的数量、后继指针域。
1.初始化链表,含表头节点,表头不存放有效数据,只是为了操作的方便。
2.从文本文件中读取单词。
3.将该单词与链表中的节点单词比较。假如相同,则单词数量增1,比较结束;否则继续跟后一节点单词比较,直到链表结尾。当比较至表尾时,则新增节点,并初始化之(节点单词赋当前单词,单词数量赋1...)。
4.继续读取单词、比较,直到文本结束。
5.遍历链表。按类似“I=2 AM=2 A=2 BOY=1 GIRL=1”的格式输出。

说明:从文本文件中读取单词时,考虑到单词间以空格为分隔符,应该如何定位至文本的当前读取位置,对于这一点我还没有好的方法。

板凳

这里我用 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.

我来回复

您尚未登录,请登录后再回复。点此登录或注册