Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > скорость проверки условий


Автор: sgentstuff 19.7.2006, 08:03
есть много вот таких условий, как можно увеличить скорость проверки, может нужно в корне что-то поменять или подругому никак?

Код

  else if (s2 = 'me') or (s2 = 'tur') or (s2 = 'na')or (s2 = 'afr')or (s2 = 'aust')
                or (s2 = 'we')or (s2 = 'ee') or (s2 = 'fe') or (s2 = 'franc') or (s2 = 'inmar')
                or (s2 = 'thrya') or (s2 = 'csa') or (s2 = 'asi') or (s2 = 'uae') or (s2 = 'can')
                or (s2 = 'usa') or (s2 = 'pak') or (s2 = 'ind') or (s2 = 'afr')  or (s2 = 'chi')
                or (s2 = 'germ')   or (s2 = 'iridi')


               

Автор: skyboy 19.7.2006, 08:21
sgentstuff, ну ты спросил! А откуда переменная берётся? Если, например, ты её вытягиваешь ихз базы, то можно посоветовать сравнивать числовые идентификаторы(мало ли, может вышло бы что-нить типа "if *(id>3) AND (id<12)"). Если у тебя приходит на порт в виде сигнала, тоже можно отсеят. Например, наложив на пришедший сигнал битовую маску.. 
Если речь же именно об этом варианте, то ответ "нет". Других конструкций, более быстрых чем if, в этом случае не предвидится. Разве что отсортируй совпадения по мере уменьшения вероянтости(сначала - самое вероятное) и отключи флаг компиляции "Полная эмуляция логического выражения". 

Автор: Romikgy 19.7.2006, 09:01
sgentstuff, я так понимаю строки сравниваешь, можно предложить вариант со сравнением посимвольно , имхо будет быстрее 

Автор: Alexeis 19.7.2006, 09:15
sgentstuff, не знаю на сколько здесь критично использование именно строк, но можно все строковые константы, заменить перечисляемым типом и проверить попадает ли число во множество состоящее из этих констант. 

Автор: sgentstuff 19.7.2006, 09:32
Цитата(alexeis1 @ 19.7.2006,  09:15)
sgentstuff, не знаю на сколько здесь критично использование именно строк, но можно все строковые константы, заменить перечисляемым типом и проверить попадает ли число во множество состоящее из этих констант.

alexeis1 - и намного быстрее будет работать?

Добавлено @ 09:36 
Цитата(Romikgy @ 19.7.2006,  09:01)
sgentstuff, я так понимаю строки сравниваешь, можно предложить вариант со сравнением посимвольно , имхо будет быстрее

как это сделать?  

Автор: BUGOR 19.7.2006, 09:37
sgentstuff, я бы использовал регулярные выражения, по крайней мере из всего предложенного на мой взгляд наиболее рациональный и довольно быстрый способ. 

Автор: Matematik 19.7.2006, 09:43
Можно еще запихнуть строки в StringList отсортировать и делать так
Код

if StringList.IndexOf(s2)<>-1 then
 

Автор: Romikgy 19.7.2006, 09:47
BUGOR, 
Цитата(BUGOR @  19.7.2006,  08:37 Найти цитируемый пост)
я бы использовал регулярные выражения, по крайней мере из всего предложенного на мой взгляд наиболее рациональный и довольно быстрый способ. 

не быстрее чем простое сравнение строк, сам подумай smile
Цитата(alexeis1 @  19.7.2006,  08:15 Найти цитируемый пост)
ожно все строковые константы, заменить перечисляемым типом и проверить попадает ли число во множество состоящее из этих констант. 

А сравнивать строковой элемент на нахождение индекса , не будет тоже самое, что предложил автор?

Цитата(sgentstuff @  19.7.2006,  08:32 Найти цитируемый пост)
как это сделать?  

Этот вариант намного муторнее , чем простое сравнение строк, но имхо быстрее , берем иследуемую строку и по очереди берем 1 символ и сравниваем потом второй и т.д.
одно единственное надо подготовить с чем сравнивать , как бы создать дерево , например для твоего варианта
Код

if (s2 = 'me') or (s2 = 'tur') or (s2 = 'na')or (s2 = 'afr')or (s2 = 'aust')    
                or (s2 = 'we')or (s2 = 'ee') or (s2 = 'fe') or (s2 = 'franc') or (s2 = 'inmar')    
                or (s2 = 'thrya') or (s2 = 'csa') or (s2 = 'asi') or (s2 = 'uae') or (s2 = 'can')    
                or (s2 = 'usa') or (s2 = 'pak') or (s2 = 'ind') or (s2 = 'afr')  or (s2 = 'chi')    
                or (s2 = 'germ')   or (s2 = 'iridi')

начало или далее будет таким буква t начинается во втором условии первой строки и первом условии третьей , так вот вместо прохода по каждому условию будет проходить по дереву, имхо количество условий уменьшится

PS а чем не подошел обычное сравнение строк?

Добавлено @ 09:49 
Matematik, самый простой в исходнике код, но он будет медленее чем обычное сравнение строк 

Автор: sgentstuff 19.7.2006, 09:50
Цитата(Matematik @ 19.7.2006,  09:43)
Можно еще запихнуть строки в StringList отсортировать и делать так
Код

if StringList.IndexOf(s2)<>-1 then

и это быстрее будет работать, ведь стринг лист теми же or будет проверять, или нет?  

Автор: Alexeis 19.7.2006, 09:50
Цитата(sgentstuff @  19.7.2006,  09:32 Найти цитируемый пост)
 - и намного быстрее будет работать?

Еще как! - будут ведь сравниватся не строки, а индексы констант в множестве, но плохо, что может понадобится сама строка, тогда можно сделать масив типа.

Код

var
  n : array[me, tur, na] = ('me', 'tur', 'na');

и иметь строковое представление.

Добавлено @ 09:52 
Цитата(sgentstuff @  19.7.2006,  09:50 Найти цитируемый пост)
и это быстрее будет работать, ведь стринг лист теми же or будет проверять, или нет? 

Еще как медленно, он ведь будет еще каждый раз организовывать поиск в строке, для нахождения индекса. 

Автор: dvamaster 19.7.2006, 09:54
Цитата(Matematik @  19.7.2006,  12:43 Найти цитируемый пост)
Можно еще запихнуть строки в StringList отсортировать и делать так

отнюдь не быстрее, он сравнивает в цикле все строки, а потом индекс выдает

Мона так

Код

type
  slist = set of ('me', 'tur', 'na', ...)
...
if (s2 in slist) then
  ...
 

Автор: BUGOR 19.7.2006, 09:55
Вообще, если такие условия используются в цикле и их много, то нужно что-то в корне менять, ибо в любом случае много ты не выиграешь ни на одном предложенном способе, а если сравнения выполняются не в цикле, то речь идёт больше о "красоте" и рациональности кода, то я всё же настаиваю на регулярных выраженияхsmile 

Автор: sgentstuff 19.7.2006, 09:56
PS а чем не подошел обычное сравнение строк?
дело в том что этих условий  у меня будет около 200 штук, и эта проверка вставленна в очень большой цикл, и теперь моя прога работает несколько часов, все из-за того что проверяется много условий, вот я и хотел как-то оптимизировать 

Автор: Romikgy 19.7.2006, 09:57
Цитата(dvamaster @  19.7.2006,  08:54 Найти цитируемый пост)
Мона так

а такое откомпилится? 

Автор: sgentstuff 19.7.2006, 10:01
Цитата(dvamaster @ 19.7.2006,  09:54)
Цитата(Matematik @  19.7.2006,  12:43 Найти цитируемый пост)
Можно еще запихнуть строки в StringList отсортировать и делать так

отнюдь не быстрее, он сравнивает в цикле все строки, а потом индекс выдает

Мона так

Код

type
  slist = set of ('me', 'tur', 'na', ...)
...
if (s2 in slist) then
  ...

на счет стринг листа, если отсортировать как предложили и потом сравнивать может все-таки быстрее будет? 

Автор: Romikgy 19.7.2006, 10:01
Цитата(sgentstuff @  19.7.2006,  08:56 Найти цитируемый пост)
 этих условий  у меня будет около 200 штук

имхо это не так много условий, конечно если они не вызываются пол милиона раз,
а вообще я бы посоветовал, где то рядом с каждой строкой держать ключ который сравнивать,
кса можно еще поигратся с указателями и преобразованиями в целые числа

Добавлено @ 10:05 
sgentstuff, а могут ли в проверяемых строках быть допустим такие
'tsu' и 'tsur'? 

Автор: Alexeis 19.7.2006, 10:11
Цитата(Romikgy @  19.7.2006,  09:57 Найти цитируемый пост)
а такое откомпилится? 
 нет, конечно, имена элементов множества ведь существуют только в исходном коде!

Добавлено @ 10:19 
Цитата(sgentstuff @  19.7.2006,  10:01 Найти цитируемый пост)
на счет стринг листа, если отсортировать как предложили и потом сравнивать может все-таки быстрее будет? 

Если все строки такие маленькие 3-5 симвотов, то лучше оставить как есть. 

Автор: Girder 19.7.2006, 10:45
xxx='|me|tur|na|afr';
if pos('|'+s2,xxx) then... 

Автор: Romikgy 19.7.2006, 10:56
Girder, я тоже так подумал только два замечания:
1. это дельфи форум  smile 
2. если будет
Код

xxx='|me|turs|tur|na|afr';
if pos('|'+s2,xxx) then...  

tur - будет строкой поиска то никогда правильного результата не получишь , плюс символ | не может быть в строках   

Автор: sgentstuff 19.7.2006, 11:13
Цитата(Romikgy @ 19.7.2006,  10:01)
Цитата(sgentstuff @  19.7.2006,  08:56 Найти цитируемый пост)
 этих условий  у меня будет около 200 штук

имхо это не так много условий, конечно если они не вызываются пол милиона раз,
а вообще я бы посоветовал, где то рядом с каждой строкой держать ключ который сравнивать,
кса можно еще поигратся с указателями и преобразованиями в целые числа

Добавлено @ 10:05 
sgentstuff, а могут ли в проверяемых строках быть допустим такие
'tsu' и 'tsur'?

неа! 

Автор: Romikgy 19.7.2006, 11:17
имхо самое быстро будет так
Код

var sl: TStringList;
findtext: string;
begin
sl:=TStringList.Create;
sl.Add('turist');
sl.Add('turf');
sl.Add('tur');
sl.Add('rgy');
sl.Delimiter:='+';
findtext:= 'tur';
if Pos('+'+findtext+'+',sl.DelimitedText)<>0 then
// если есть совпадение
MessageBox(HWND(nil),Pchar('Est'),Pchar('Hi'),0)
else
//если нет совпадения
MessageBox(HWND(nil),Pchar('Net'),Pchar('Hi'),0);
;
sl.Free;

end;
 

Автор: sgentstuff 19.7.2006, 11:19
Цитата(alexeis1 @ 19.7.2006,  09:15)
sgentstuff, не знаю на сколько здесь критично использование именно строк, но можно все строковые константы, заменить перечисляемым типом и проверить попадает ли число во множество состоящее из этих констант.

покажите пример пожалуйста! 

Автор: Alexeis 19.7.2006, 11:19
ну тогда можно чуть поправить
Код

xxx := #1'me'#1'turs'#1'tur'#1'na'#1'afr'#1;
if pos(#1+s2+#1, xxx) <> 0
  then... 


Добавлено @ 11:26 
Цитата(sgentstuff @  19.7.2006,  11:19 Найти цитируемый пост)
покажите пример пожалуйста!

Код

  type
    strs = (me, tur, na);

  var
    n : array[strs] of AnsiString = ('me', 'tur', 'na');

procedure TForm1.btn1Click(Sender: TObject);
var
  strset : set of strs;
begin
  strset := [me, tur, na];
  if s2 in strset
  then
    ShowMessage('равно одному из значений');
end;
  

Автор: Mechanic 19.7.2006, 12:40
А я бы составил строку из всех вариантов, типа
Код

Model := #9+'tur'+#9+'na'+#9+'afr'+#9+'aust'..... +#9;
if Pos(#9+s2+#9,Model)=0 then ...


Ой, уже показал этот вариант alexeis1. Только похоже, этот самый быстрый, по-любому. 

Автор: sgentstuff 19.7.2006, 12:42
Цитата(Romikgy @ 19.7.2006,  11:17)
имхо самое быстро будет так
Код

var sl: TStringList;
findtext: string;
begin
sl:=TStringList.Create;
sl.Add('turist');
sl.Add('turf');
sl.Add('tur');
sl.Add('rgy');
sl.Delimiter:='+';
findtext:= 'tur';
if Pos('+'+findtext+'+',sl.DelimitedText)<>0 then
// если есть совпадение
MessageBox(HWND(nil),Pchar('Est'),Pchar('Hi'),0)
else
//если нет совпадения
MessageBox(HWND(nil),Pchar('Net'),Pchar('Hi'),0);
;
sl.Free;

end;

проверил я этот способ, скорость работы таже! 

Автор: Romikgy 19.7.2006, 12:44
значит тормозит не в условиях! 

Автор: sgentstuff 19.7.2006, 12:47
пишу я так, но в переменных не может быть пробела
Код

type    
    nurset = (ark-k, nursat, nur, nurs);


Добавлено @ 12:49 
Цитата(Romikgy @ 19.7.2006,  12:44)
значит тормозит не в условиях!

почему этот способ не берет первую переменную? 

Автор: Girder 19.7.2006, 13:00
Цитата(sgentstuff @  19.7.2006,  13:42 Найти цитируемый пост)
скорость работы таже!
А ты список каждый раз создаеш?  smile 
  

Автор: sgentstuff 19.7.2006, 13:00
Romikgy - твой способ почему-то неберет первую переменную, видимо у нее нет впереди '+'

Добавлено @ 13:02 
Цитата(Girder @ 19.7.2006,  13:00)
Цитата(sgentstuff @  19.7.2006,  13:42 Найти цитируемый пост)
скорость работы таже!
А ты список каждый раз создаеш?  smile

1 раз! 

Автор: Romikgy 19.7.2006, 13:45
сделай так
Код

if Pos(findtext+'+',sl.DelimitedText)<>0 then

и в конце массива добавлений добавь
Код

sl.Add('');
 

Автор: sgentstuff 19.7.2006, 13:47
Цитата(Mechanic @ 19.7.2006,  12:40)
А я бы составил строку из всех вариантов, типа
Код

Model := #9+'tur'+#9+'na'+#9+'afr'+#9+'aust'..... +#9;
if Pos(#9+s2+#9,Model)=0 then ...


Ой, уже показал этот вариант alexeis1. Только похоже, этот самый быстрый, по-любому.

этот способ затестил, чуть чуть быстрее

Добавлено @ 13:57 
alexeis1 - компилятор не пропускает переменную ark-k, что делать?
Код

type
nurset = (ark-k, nursat, nur, nurs);

begin
s2:='ark-k';
if s2 in strset then







 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)