2011-03-10 22 views

Respuesta

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

segundo PosEx se podría escribir "offset: = PosEx (subcadena, texto, offset + longitud (subcadena));" si no se preocupan por subcadenas recurrentes. ;) –

+1

@ A.Bouchez: Sí, eso es muy cierto. Incluso diría que debes usar la longitud real de la subcadena * especialmente * si te preocupa la entrada (patológica) como 'Ocurrencias ('ddd', 'dddddddd')'. Yo he cambiado eso. Por supuesto, para el rendimiento, es una buena idea guardar 'len: = length (Substring)' antes del bucle (¿o es el compilador lo suficientemente inteligente como para hacer esta optimización por sí mismo?). –

+1

+1 Probablemente usaría una var y almacenaría la longitud de SubString en ella para evitar las llamadas repetidas a Length, pero dado que Length realmente solo lee una compensación negativa de @SubString, probablemente no sea una gran actuación de todos modos. . :) –

8

Una de las maneras más inteligentes que he visto hacer esto:

{ 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

Sí, esta es una forma muy inteligente. En realidad, RRUZ publicó ayer este método como una respuesta, pero luego, por alguna razón, lo eliminó. El comentario que le hice a su pregunta fue * Bueno, esta es una "edición especial", de hecho. En cuanto al rendimiento, sin embargo, está lejos de ser ideal, me temo ... * Para ser honesto, creo que no hay ninguna razón para usar este método cuando hay muchos más que no están más completados. Aún así, te habría dado un +1 si no me hubiera sentido mal por RRUZ al hacerlo ... –

+0

Bueno, te doy un +1 de todos modos. Como "solo" obtuviste 1683 como representante, no puedes ver las publicaciones borradas. Pero si RRUZ invalida su pregunta, prometo que le daré un +1 también. –

+1

Inteligente, pero lento, y desperdicia memoria. –

4

Si usted se encuentra con frecuencia en busca ocurrencias en un gran cuerpo de textoy el rendimiento se convierte en una problema, puede probar el Boyer-Moore search algorithm.

el peor de los casos para encontrar todas las ocurrencias en un texto necesita alrededor de 3 N comparaciones

Una aplicación en Delphi se puede encontrar en nuestro propio SO here

Necesito tres funciones fast-on-large-strings : búsqueda rápida, búsqueda rápida y reemplazar, y conteo rápido de subcadenas en una cadena.

+1

+1 para saber qué es la búsqueda de Boyer-Moore. –

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

Incluya alguna descripción o explicación de su código en lugar de solo responder con un fragmento de código. – davidcondrey

+1

Esto parece una variación de la respuesta aceptada. ¿Podría explicar por qué esto es diferente y cuáles son los beneficios de hacerlo de esta manera? – andrewsi

+0

Usar el bucle "repetir" en este caso es más elegante, porque la búsqueda debe realizarse al menos una vez. – GoodMan

Cuestiones relacionadas