2011-08-17 38 views
8

這個問題是討論如何編寫拼寫糾正器,並且不是 Delphi Spell Checker組件的重複。Delphi中的拼寫校正器代碼?

兩年前,我在Python中找到並使用了Peter Norvig at his website的拼寫糾正碼。但表現似乎不高。非常有趣的是,最近實現相同任務的更多語言已被添加到他的網頁列表中。

在彼得的頁面有些線路包括像語法:

[a + c + b  for a, b in splits for c in alphabet] 

如何把它翻譯成德爾福?

我對如何使用相同理論的Delphi專家感興趣,並且使用一些合適的線和可能的平庸或更好的性能完成相同的任務。這不是爲了低估任何語言,而是要學習如何以不同的方式執行任務。

非常感謝。

[編輯]

我引用Marcelo Toledo誰有助於C版的話說:「......雖然這篇文章[C版]的目的是爲了顯示算法,不突出Python的......」 。根據他的文章,雖然他的C版本排在第二位,但是當字典文件很大時,他的版本是高性能的。所以這個問題並沒有突出任何語言,而是要求提供delphi解決方案,儘管彼得在指導谷歌研究方面有影響力,但並不打算用於競爭。

[更新]

我被大衛的建議啓發和學習彼得頁的理論和程序。一個非常粗糙和低效率的例程已經完成,與其他語言略有不同,我的是GUI。我是Delphi的初學者和學習者,我不敢發佈我的完整代碼(它寫得不好)。我將概述我是如何做到的。歡迎您的評論,以便日常工作得到改善。

我的硬件和軟件都很舊。這足以我的工作(我的專長是不相關的計算機或程序)

AMD Athlon Dual Core Processor 
2.01 Ghz, 480 Memory 
Windows XP SP2 
IDE Delphi 7.0 

這是快照和「正確」二字的處理時間記錄。 我試過Gettickcount,Tdatetime和Queryperformancecounter來跟蹤word的正確時間,但gettickcount和Tdatetime會爲每次檢查輸出o ms,所以我必須使用 Queryperformancecounter。也許還有其他方法可以更精確地做到這一點。

總行數爲72,不包括記錄檢查時間的函數。行數可能不是Marcelo上面提到的尺度。這篇文章討論如何以不同的方式完成這項任務。 SO的Delphi專家當然會使用最少的線路來實現最佳性能。

Spell Checker

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個UNIQUE可能性。當然,建議的話也會包括更多。

如果帶有edits2,校正的響應時間明顯延遲,因爲它將數據增加了約200倍。但是我發現一些建議的更正顯然是不可能的,因爲打字員不會輸入一個錯誤的單詞,這個錯誤單詞將會出現在已更正的單詞列表中。因此,如果big.txt文件足夠大以包含更多正確的單詞,編輯距離1會更好。

下面是跟蹤編輯2正確時間的快照。

enter image description here

+2

您是否希望我們在Delphi中實現它,並告訴您有多少行和性能如何?聽起來更像是一場比賽,而不是一個嚴肅的問題。無論如何,我們無法在不同的機器上測量結果,並將其與Peter Norvig的結果進行比較。 -1,至少在你解釋你真正想知道的內容之前。 – 2011-08-17 08:54:00

+0

@daemon_x,我想知道如何在delphi中做到這一點。如何在範圍內(len(word)+ 1)]或「[a + c + b [1: ]代表a,b代表拼音字母c,如果b]「。彼得列舉了任務的語言並不意味着競爭,但表明多種語言都可以做到這一點。我沒有測試過所有的語言版本。儘管一些語言標註的行數較少,但並不意味着更好的性能。 – Dylan

+0

@ user482742 - 刪除了-1;將代碼翻譯成Delphi可能會非常有趣,但對SO來說這不是一個好問題(任務)。 – 2011-08-17 09:11:34

回答

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功能。