这个问题是讨论如何编码拼写纠正器而不是重复 Delphi Spell Checker组件。
两年前,我在Python中发现并使用了Peter Norvig at his website的拼写纠正器代码。但表现似乎并不高。非常有趣的是,最近在他的网页列表中附加了更多实现相同任务的语言。
Peter的页面中的某些行包含如下语法:
[a + c + b for a, b in splits for c in alphabet]
如何将其翻译成delphi?
我对SO的Delphi专家将如何使用相同的理论并使用一些合适的线和可能的平庸或更好的性能执行相同的任务感兴趣。这不是为了贬低任何语言,而是要学会比较他们如何以不同方式实施任务。
非常感谢。
[编辑]
我会引用贡献C版本的Marcelo Toledo,说“......虽然本文[C版本]的目的是展示算法,而不是突出显示Python ......”。虽然他的C版本排在第二位,但根据他的文章,他的版本在字典文件庞大时性能很高。所以这个问题并不突出任何语言,而是要求delphi解决方案,尽管彼得在指导Google Research方面具有影响力,但它并不适合竞争。
[更新]
我被大卫的建议所启发,并研究了彼得页面的理论和惯例。这是一个非常粗略和低效的例程,与其他语言略有不同,我的是GUI。我是Delphi的初学者和学习者,我不敢发布我的完整代码(写得不好)。我将概述我是如何做到的。欢迎您发表评论,以便改进例程。
我的硬件和软件都很旧。这对我的工作来说已经足够了(我的专业不是计算机或程序相关的)
AMD Athlon Dual Core Processor
2.01 Ghz, 480 Memory
Windows XP SP2
IDE Delphi 7.0
这是“正确”字处理时间的快照和记录。 我尝试了Gettickcount,Tdatetime和Queryperformancecounter来跟踪正确的单词时间,但gettickcount和Tdatetime将为每个检查输出o ms,所以我必须使用 QueryPerformanceCounter的。也许还有其他方法可以更精确地完成它。
总行数为72,不包括记录检查时间的功能。如上所述,Marcelo的行数可能不是标准。该帖子讨论了如何以不同方式完成任务。 SO的Delphi专家当然会使用最小的线来实现最佳性能。
procedure Tmajorform.FormCreate(Sender: TObject);
begin
loaddict;
end;
procedure Tmajorform.loaddict;
var
fs: TFilestream;
templist: TStringlist;
p1: tperlregex;
w1: string;
begin
//load that big.txt (6.3M, is Adventures of Sherlock Holmes)
//templist.loadfromstream
//Use Tperlregex to tokenize ( I used regular expression by [Jan Goyvaerts][5])
//The load and tokenize time is about 7-8 seconds on my machine, Maybe there are other ways to
//speed up loading and tokenizing.
end;
procedure Tmajorform.edits1(str: string);
var
i: integer;
ch: char;
begin
// This is to simulate Peter's page in order to fast generate all possible combinations.
// I do not know how to use set in delphi. I used array.
// Peter said his routine edits1 would generate 494 elements of 'something'. Mine will
// generate 469. I do not know why. Before duplicate ignore, mine is over 500. After setting
// duplicate ignore, there are 469 unique elements for 'something'.
end;
procedure Tmajorform.correct(str: string);
var
i, j: integer;
begin
//This is a loop and binary search to add candidate word into list.
end;
procedure Tmajorform.Button2Click(Sender: TObject);
var
str: string;
begin
// Trigger correct(str: string);
end;
似乎通过Tfilestream,它可以将负载增加1-2秒。我尝试使用CreateFileMapping方法但失败了,看起来有点复杂。也许还有其他方法可以快速加载大文件。因为考虑到语料库的可用性,这个big.txt不会很大,所以应该有更有效的方法来加载更大和更大的文件。
另一点是Delphi 7.0没有内置的正则表达式。我看看在Perter的页面上进行拼写检查的其他语言,它们主要是直接调用它们的内置正则表达式。当然,真正的专家不需要任何内置的类或库,可以自己构建。对于初学者来说,一些类或库是方便的。
欢迎您发表评论。
[更新]
我继续研究并进一步包括edits2功能(编辑距离2)。这将增加大约另外12行代码。彼得说编辑距离2几乎涵盖了所有可能性。 '某事'将有114,324种可能性。我的功能将为它生成102,727个独特的可能性。当然,建议的单词也会包含更多内容。
如果使用edits2,响应修正的时间显然会延迟,因为它会使数据增加约200倍。但我发现一些建议的更正显然是不可能的,因为打字员不会输入将在长期更正的单词列表中的错误单词。因此,如果big.txt文件足够大以包含更多正确的单词,则编辑距离1会更好。
以下是跟踪修改2正确时间的快照。
答案 0 :(得分:8)
这是一个Python列表理解。它形成了分裂和字母的笛卡尔积。
每个分裂项都是一个元组,它被解压缩到a和b中。每个字母表项都放在一个名为c的变量中。然后将3个变量连接起来,假设它们是字符串。列表推导表达式的结果是一个列表,其中包含a + c + b形式的元素,笛卡尔积中每个项目的一个元素。
在Python中,它可以等效地编写为
res = []
for a, b in splits:
for c in alphabets:
res.append(a + c + b)
在Delphi中它将是
res := TStringList.Create;
for split in splits do
for c in alphabets do
res.Add(split.a + c + split.b);
我建议你阅读Python list comprehensions以更好地理解这个非常强大的Python功能。