2011-03-10 60 views

回答

37
function Occurrences(const Substring, Text: string): integer; 
var 
    offset: integer; 
begin 
    result := 0; 
    offset := PosEx(Substring, Text, 1); 
    while offset <> 0 do 
    begin 
    inc(result); 
    offset := PosEx(Substring, Text, offset + length(Substring)); 
    end; 
end; 
+2

第二PosEx可以寫 「偏移:= PosEx(串,文字,膠印+長度(串));」 如果你不關心復發子。 ;) – 2011-03-10 20:27:34

+1

@ A.Bouchez:是的,這是非常真實的。我甚至會說你應該使用子字符串的實際長度*特別是*如果你關心像'Occurrences('ddd','dddddddd')'這樣的(病態)輸入。我改變了這一點。當然,對於性能來說,在循環之前保存'len:= length(Substring)'是一個好主意(或者編譯器足夠聰明,可以自己完成這種優化?)。 – 2011-03-10 20:34:21

+1

+1我可能會使用一個var並在其中存儲SubString的長度以避免重複調用Length,但由於Length實際上只是從@SubString讀取一個負偏移量,所以它可能不會有太大的性能影響。 :) – 2011-03-10 20:38:29

8

一個我見過這樣做的最聰明的方法:

{ Returns a count of the number of occurences of SubText in Text } 
function CountOccurences(const SubText: string; 
          const Text: string): Integer; 
begin 
    if (SubText = '') OR (Text = '') OR (Pos(SubText, Text) = 0) then 
    Result := 0 
    else 
    Result := (Length(Text) - Length(StringReplace(Text, SubText, '', [rfReplaceAll]))) div Length(subtext); 
end; { CountOccurences } 
+0

是的,這是一個非常聰明的方法。實際上,RRUZ昨天發佈了這個方法作爲答案,但之後由於某種原因,他刪除了它。我對他的問題發表的評論是*確實,這是一個「特別版」。然而,從性能角度來看,這是遠遠不夠理想的,恐怕...... *說實話,我認爲沒有理由使用這種方法的時候,有更高性能的方法,而不是更復雜。不過,如果我對RRUZ沒有感到不好,我會給你一個+1 ... – 2011-03-11 14:25:41

+0

好吧,無論如何,我給你+1。由於你「只」在代表1683年,你看不到已刪除的帖子。但是如果RRUZ取消刪除他的問題,我保證我也會給他一個+1。 – 2011-03-11 14:31:03

+1

聰明但緩慢,浪費記憶。 – 2011-03-11 21:32:23

4

如果你發現自己經常在正文文本的搜索出現次數和性能成爲問題,你可以試試Boyer-Moore search algorithm

最壞情況下找到所有出現 文本大約需要3N 比較

在Delphi中的實現可以發現在我們自己的SO here

我需要三個快速大字符串 功能:快速搜索,快速搜索 並替換,並快速計數 字符串中的子串。

+1

+1瞭解Boyer-Moore搜索的內容。 – 2011-03-11 21:32:44

1

uses 
    StrUtils;  

function Occurrences(const Substring, Text: string; 
    const ignoreUppercase: Boolean = false): Integer; 
var 
    inSubstring, inText: string; 
    inPos: Integer; 
begin 
    Result:= 0; 

    if (Substring = '') or (Text = '') then 
    Exit; 

    if ignoreUppercase then 
    begin 
    inSubstring:= AnsiLowerCase(Substring); 
    inText:= AnsiLowerCase(Text); 
    end 
    else 
    begin 
    inSubstring:= Substring; 
    inText:= Text; 
    end; 

    inPos:= 1; 

    repeat 
    inPos:= posEx(inSubstring, inText, inPos); 
    if inPos > 0 then 
    begin 
     Inc(Result); 
     inPos:= inPos + Length(inSubstring); 
    end; 
    until inPos = 0; 
end; 

+1

請包括一些描述或對代碼的解釋,而不是僅僅回答一段代碼片段。 – davidcondrey 2014-07-15 21:22:42

+1

這看起來像接受答案的變體。你能解釋爲什麼這是不同的,這樣做的好處是什麼? – andrewsi 2014-07-15 21:39:16

+0

在這種情況下使用循環「重複」更優雅,因爲搜索必須至少保留一次。 – GoodMan 2014-07-28 17:22:32

相關問題