Альтернативы StringReplace для улучшения производительности

10
задан Ricardo Acras 26 September 2008 в 14:22
поделиться

6 ответов

Попробуйте FastStrings.pas от Peter Morris.

7
ответ дан 3 December 2019 в 14:54
поделиться

При использовании Delphi 2009 эта операция приблизительно в 3 раза быстрее с TStringBuilder, чем с ReplaceString. Это - безопасный Unicode, также.

Я использовал текст из http://www.CodeGear.com со всеми случаями" <" и">" измененный на "&lt;" и "&gt;" как моя начальная точка.

Включая строковые присвоения и создающие/освобождающие объекты, они взяли приблизительно 25 мс и 75 мс соответственно в моей системе:

function TForm1.TestStringBuilder(const aString: string): string;
var
  sb: TStringBuilder;
begin
  StartTimer;
  sb := TStringBuilder.Create;
  sb.Append(aString);
  sb.Replace('&gt;', '>');
  sb.Replace('&lt;', '<');
  Result := sb.ToString();
  FreeAndNil(sb);
  StopTimer;
end;

function TForm1.TestStringReplace(const aString: string): string;
begin
  StartTimer;
  Result := StringReplace(aString,'&gt;','>',[rfReplaceAll]) ;
  Result := StringReplace(Result,'&lt;','<',[rfReplaceAll]) ;
  StopTimer;
end;
8
ответ дан 3 December 2019 в 14:54
поделиться

Необходимо определенно посмотреть на страницы проекта Fastcode: http://fastcode.sourceforge.net/

Они выполнили проблему для более быстрого StringReplace (Проблема Ansi StringReplace), и 'победитель' был в 14 раз быстрее, чем Delphi RTL.

Несколько из функций fastcode были включены в самом Delphi в последних версиях (D2007 на, я думаю), таким образом, повышение производительности может варьироваться существенно, в зависимости от которой версии Delphi Вы используете.

Как упомянуто прежде, необходимо действительно смотреть на основанное на Unicode решение, если Вы серьезно относитесь к обработке XML.

6
ответ дан 3 December 2019 в 14:54
поделиться

Проблема состоит в том, что Вы выполняете итерации всего размера строки дважды (один для замены &gt;> и другой для замены &lt; <).

Необходимо выполнить итерации с для и просто проверить вперед каждый раз, когда Вы находите a и для gt; или лейтенант; и сделайте непосредственную замену и затем пропуск 3 символов ((g|l) t;). Таким образом, это может сделать это в пропорциональное время к размеру строки xml. Текст.


Простой пример C#, поскольку я не знаю Delphi, но должен сделать, чтобы Вы в общих чертах поняли.

String s = "&lt;xml&gt;test&lt;/xml&gt;";
char[] input = s.ToCharArray();
char[] res = new char[s.Length];
int j = 0;
for (int i = 0, count = input.Length; i < count; ++i)
{
    if (input[i] == '&')
    {
        if (i < count - 3)
        {
            if (input[i + 1] == 'l' || input[i + 1] == 'g')
            {
                if (input[i + 2] == 't' && input[i + 3] == ';')
                {
                    res[j++] = input[i + 1] == 'l' ? '<' : '>';
                    i += 3;
                    continue;
                }
            }
        }
    }

    res[j++] = input[i];
}
Console.WriteLine(new string(res, 0, j));

Это производит:

<xml>test</xml>
3
ответ дан 3 December 2019 в 14:54
поделиться

Непротестированное преобразование кода C# записано Jorge Ferreira.

function ReplaceLtGt(const s: string): string;
var
  inPtr, outPtr: integer;
begin
  SetLength(Result, Length(s));
  inPtr := 1;
  outPtr := 1;
  while inPtr <= Length(s) do begin
    if (s[inPtr] = '&') and ((inPtr + 3) <= Length(s)) and
       (s[inPtr+1] in ['l', 'g']) and (s[inPtr+2] = 't') and
       (s[inPtr+3] = ';') then
    begin
      if s[inPtr+1] = 'l' then
        Result[outPtr] :=  '<'
      else
        Result[outPtr] := '>';
      Inc(inPtr, 3);
    end
    else begin
      Result[outPtr] := Result[inPtr];
      Inc(inPtr);
    end;
    Inc(outPtr);
  end;
  SetLength(Result, outPtr - 1);
end;
2
ответ дан 3 December 2019 в 14:54
поделиться

Systools (Turbopower, теперь открытый исходный код) сделал, чтобы ReplaceStringAllL функционировал, который делает всех их в строке.

2
ответ дан 3 December 2019 в 14:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: