2009-08-15 2 views
2

Мне нужно сравнить частичную строку «SKILL_______EU_______WAND_______CLERIC_______BASE_____01» с «SKILL». Он предназначен для проверки того, являются ли первые четыре символа «SKILL». или только первый символ, здесь нужна оптимизация!Самый быстрый способ сравнить частичную строку?

Мои проблемы:

  1. Я не знаю, как сделать оптимизированное сравнение.
  2. Повторяется 35 000 раз, поэтому должно быть что-то очень быстро.

Спасибо!

+6

Как могут первые 4 персонажа быть «НАВЫК» ?! – jason

+0

Вы пытаетесь перефразировать мой вопрос? –

+3

Lol! Нет, я не пытаюсь перефразировать вас. Я просто указываю, что первые четыре символа этой строки никогда, никогда не будут «НАВЫК». – jason

ответ

11

Использование StrUtils.AnsiStartsStr для чувствительно к регистру, StrUtils.AnsiStartsText для регистронезависимого (добавить StrUtils к вашему пункту изеза)

6

35000 повторений действительно не так много в наши дни, это, вероятно, не имеет значения, что вы делаете.

+1

Разумное замечание, я не получаю downvotes. –

+0

Это разумная мысль. Сделайте это самым надежным способом, независимо от того, как медленно, затем сохраните результаты и больше не делайте этого. – quillbreaker

+1

Разумным, как бы то ни было, на самом деле он не отвечает на вопрос, каков бы ни был этот вопрос. Поэтому я, конечно, мог понять, что это проголосовали. –

1

Я думаю, что процедуры Delphi довольно оптимизированы и быстры, поэтому просто используйте их.

var 
    position : Integer; 

begin 
    // AnsiPos 
    // returns the position of a substring in a string 
    // or 0 if the substring isn't found 
    position := AnsiPos('SKILL', 'SKILL_______EU_______WAND_______CLERIC_______BASE_____01'); 
end; 
+3

Это будет продолжаться при сканировании всей доменной строки, даже если 1-й символ неравный. –

0

Я много о Delphi не знаю, но я думаю, что (на любом языке/рамочный/платформы) Regex это самый быстрый способ для строки сканирования ...

Вы не точно указать все условия вы ищете ...

+0

Regex очень полные, но они не считают себя быстрыми. Вы должны использовать регулярное выражение для сложных поисков, а не тривиальных, особенно если скорость не имеет значения. – Lepidosteus

+1

«Не считается быстрым» - у вас есть ссылка на это? Большинство reg-ex сопоставляются в O (n) и очень трудно бить рукописным кодом. –

+2

@ Хенк Холтерман: простите, я должен был быть более конкретным; быстро в случае, например, в этом вопросе. Если вы хотите только проверить первые 4-5 символов строки, чтобы убедиться, что она что-то соответствует, лучше использовать функции, специально разработанные и оптимизированные для этого. – Lepidosteus

1

в случае, если вы хотите проверить только 1-й символ, вы можете сделать это следующим образом:

if 'S' = 'SKILL_______EU_______WAND_______CLERIC_______BASE_____01'[1] then 
begin 
    showmessage('SKILL'); 
end 
+0

Разве это даже компилируется? –

+0

, конечно, он компилируется. Тем не менее, я не тестировал в Delphi 2009. Я уверен, что он будет компилироваться во всех версиях Delphi. –

+0

Я не думал, что законно применять оператор скобки к строковому литералу. Но если вы скажете, что он скомпилирован, я возьму ваше слово за это. Обратите внимание: Free Pascal * не принимает этот синтаксис (даже в режиме «Delphi»). –

0

Почему бы не сделать:

function StartsWith(const AMatchStr, ATestStr : string) : boolean; 
begin 
    Result := SameText(AMatchStr, copy(ATestStr, 1, Length(AMatchStr)); 
end; 

Это не будет обрабатывать какую-либо часть ATestStr за пределами исходного текста. Bri

+0

Но он скопирует символы, не обязательно. –

+1

Почему бы не сделать это? Поскольку в библиотеке уже есть такая функция, и даже если бы это не так, было бы лучше использовать 'StrLComp', чем сделать временную копию строки. –

5

Если вы действительно хотите получить максимальную скорость, вам придется немного написать StartsWith.

// untested, case-sensitive 
Function StartsWith(const find, text : string) : Boolean; 
var i, len : integer; 
begin 
    result := true; 
    len := Min(Length(find), Length(text)); 
    For i := 1 to len do 
    Begin 
    if (find[i] <> text[i]) 
    then begin 
     result := False; 
     break; 
    end; 
    End; 
end; 
+0

орфографическая ошибка в «Длина» – bart

+8

В Delphi уже есть функция AnsiStartsStr (с учетом регистра)/AnsiStartsText (без учета регистра). Нет необходимости переопределять его. Просто используйте блок «StrUtils». –

+0

@ Андреас, ты прав, я просто не мог его найти. Просто желаю, чтобы все документы Delphi были в сети ... Я оставляю ответ, это может быть стартер для пользовательской версии. –

0

Если вы только что проверить первые 4/5 символов вы могли бы сделать

i:= Length('SKILL'); 

LeftStr('SKILL_______EU_______WAND_______CLERIC_______BASE_____01',i) = 'SKILL' 
1

Независимо от того, какое решение вы выбираете, пожалуйста, имейте в виду, на самом деле тест и тесте это против вашего тока реализация.

В противном случае вы просто угадываете, а не оптимизируете.

И имейте в виду, что premature optimization is the root of all evil.

Удачи вам!

0
if AnsiPos('SKILL', 'SKILL_______EU_______WAND_______CLERIC_______BASE_____01') > 0 then 

Я думаю, что это должно делать эту работу, я не знаю, о скорости AnsiPos, если его быстро или медленно или что-то еще. Он работает для меня всякий раз, когда я хочу сравнить фрагменты строки.AnsiPos() возвращает целочисленное значение, которое представляет начальный индекс строки, которую вы ищете.

Смежные вопросы