Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.06.20;
Скачать: [xml.tar.bz2];

Вниз

Goto оптимален?   Найти похожие ветки 

 
Sandman25 ©   (2004-06-08 12:12) [0]

Добрый день.

Пишу код вроде
with DataSet do
begin
 while not Eof do
 begin
   case Field1.Value of
     1,
     2:
       ;
     3:
       if Count1 > 3 then
       begin
         Next;
         Continue;
       end
       else
         Inc(Count1);
     4:
       if Count2 > 4 then
       begin
         Next;
         Continue;
       end
       else
         Inc(Count2);
   else
     begin
       Next;
       Continue;
     end
   end;
   ... обработка данных
   Next;
 end;
end;


Как видите, код неоптимален из-за повторяющегося фрагмента - Next;Continue. Как лучше всего от него избавиться? Меткой, флагом, вызовом локальной процедуры?


 
Digitman ©   (2004-06-08 12:21) [1]

with DataSet do
while not Eof do
 try
   case Field1.Value of
     1, 2:;
     3: if Count1 > 3 then Continue else Inc(Count1);
     4: if Count2 > 4 then Continue else Inc(Count2);
   end;
  ... обработка данных
 finally
   Next;
 end;


 
Sandman25 ©   (2004-06-08 12:31) [2]

[1] Digitman ©   (08.06.04 12:21)

Большое спасибо!
Записей мало (до 15), поэтому задержка из-за try-finally некритична.


 
Anatoly Podgoretsky ©   (2004-06-08 12:45) [3]

Это вообще лишнее      
1, 2:;
Пустой оператор


 
Sandman25 ©   (2004-06-08 12:47) [4]

[3] Anatoly Podgoretsky ©   (08.06.04 12:45)

У case есть ветвь else. См. [1].


 
Sandman25 ©   (2004-06-08 12:47) [5]

То есть не [1], а [0]


 
Anatoly Podgoretsky ©   (2004-06-08 13:12) [6]

Sandman25 ©   (08.06.04 12:47) [4]
Не обратил внимания, смотрел не на твой код, в товем нужно.


 
MU ©   (2004-06-08 15:12) [7]

with DataSet do
 while not Eof do begin
   case Field1.Value of
     3: if Count1 <= then Inc(Count1);
     4: if Count2 <= 4 then Inc(Count2);
   end;
   Next;
 end;


 
evvcom ©   (2004-06-08 15:33) [8]


> MU ©   (08.06.04 15:12) [7]

Не учел ...обработка данных. При той постановке задачи мой голос за Digitman. А вообще я бы пересмотрел такую постановку задачи. Не кажется она мне логичной, но это imho


 
MU ©   (2004-06-08 15:44) [9]

>>evvcom ©
Да-да, я это понял, сразу после... :(


 
Sandman25 ©   (2004-06-08 15:44) [10]

[8] evvcom ©   (08.06.04 15:33)

Подготовка данных для печати документа.
Если поле равно 1 или 2, то это отец и мать - они печатаются всегда и их количество не превышает одного.
Если поле равно 3, то это супруга или супруг. Если поле равно 4, то дети. В отчет должны попадать не более 3 жен (мужей) и не более 4 детей. Прочие родственники в отчет не попадают. Теперь логично? :)


 
DieHard   (2004-06-08 16:23) [11]


Count1 = 0;
Count2 = 0;
with DataSet do
begin
while not Eof do
begin
  case Field1.Value of
    3:
      Inc(Count1);
    4:
      Inc(Count2);
  end;
  if (Field1.Value in [1..4]) and (Count1 <= 3) and (Count2 <= 4) then
  begin
    ... обработка данных
  end;
  Next;
end;
end;


 
Sandman25 ©   (2004-06-08 16:27) [12]

[11] DieHard   (08.06.04 16:23)

if (Field1.Value in [1..2]) or (Field1.Value = 3) and (Count1 <= 3) or (Field1.Value = 4) and (Count2 <= 4) then

Но не очень структурно проверять значение переменной более 1 раза ИМХО


 
DieHard   (2004-06-08 16:44) [13]


Count1 = 0;
Count2 = 0;
with DataSet do
begin
while not Eof do
begin
 NeedProcessing := False;
 case Field1.Value of
   1, 2: NeedProcessing := True;
   3:
     Inc(Count1);
     NeedProcessing := Count1 <= 3;
   4:
     Inc(Count2);
     NeedProcessing := Count2 <= 4;
 end;
 if NeedProcessing then
 begin
   ... обработка данных
 end;
 Next;
end;
end;

Лишняя переменная - это структурно? ;)


 
Mim1 ©   (2004-06-08 16:50) [14]

[1] Digitman ©   (08.06.04 12:21)
[2] Sandman25 ©   (08.06.04 12:31)

finally
  Next;
end;


Чтото я не вижу смысла в этом коде. Какая разница на какой записи останется курсор при возникновении исключения.


 
Sandman25 ©   (2004-06-08 16:52) [15]

[13] DieHard   (08.06.04 16:44)

Вполне. Переделаю под Ваш вариант. Отсутствие else-секции в case очень полезно :)


 
Плохиш   (2004-06-08 16:53) [16]

>Mim1 ©   (08.06.04 16:50) [14]

Там Continue стоит ;-)


 
DieHard   (2004-06-08 16:54) [17]

[14] Mim1
Исключения не будет, этого и не требуется, просто нужно, чтобы Next выполнился в любом случае, что и обеспечивает try ... finally ... end;


 
Anatoly Podgoretsky ©   (2004-06-08 16:56) [18]

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


 
MU ©   (2004-06-08 16:57) [19]

with DataSet do
while not Eof do begin
  case Field1.Value of
    1,2:
    3  : if Count1 <= then Inc(Count1);
    4  : if Count2 <= 4 then Inc(Count2);
    else begin
      //......Обработка данных
    end;
  end;
  Next;
end;

:))


 
Sandman25 ©   (2004-06-08 17:03) [20]

Остановился на следующем варианте:

     RelatedIndex := clRelatedRelType.Value;
     case RelatedIndex of
       1,  // отец
       2:  // мать
         NeedsProcessing := True;
       3:  // супруг(и)
         begin
            Inc(MarriedCount);
            // разрешаем до 3 супругов включительно
            NeedsProcessing := MarriedCount <= 3;
            RelatedIndex := 2 + MarriedCount; // от 3 до 5
          end;
       4:  // дети
          begin
            Inc(ChildrenCount);
            // разрешаем до 4 супругов включительно
            NeedsProcessing := ChildrenCount > 4;
            RelatedIndex := 5 + ChildrenCount // от 6 до 9
          end
       else
         NeedsProcessing := False;
     end;
     if NeedsProcessing then

Решил при присвоении RelatedIndex внутри case не проверять NeedsProcessing.


 
Игорь Шевченко ©   (2004-06-08 17:06) [21]

Я бы так сделал, тоже, наверное, неоптимально:

procedure TForm1.FormCreate(Sender: TObject);

 function NeedProcessing: Boolean;
 begin
   Result := (Field1.Value in [1,2]) or ((Field1.Value = 3) and Count1 < 3)
     or ((Field1.Value = 4) and Count2 < 4);
 end;

begin
 with DataSet do begin
   while not Eof do begin
     if NeedProcessing then begin
       if Field1.Value = 3 then
         Inc(Count1)
       else if Field1.Value = 4 then
         Inc(Count2);
{   ... обработка данных }
     end;
     Next;
   end;
 end;
end;



 
Sandman25 ©   (2004-06-08 17:11) [22]

Доработанный вариант  [21] Игорь Шевченко ©   (08.06.04 17:06)

procedure TForm1.FormCreate(Sender: TObject);

function NeedProcessing: Boolean;
begin
  case Field1.Value of
    1,2:
      Result := True;
    3:
      Result := Count1 < 3;
    4:
      Result := Count2 < 4;
    else
      Result := False
  end;
end;

begin
with DataSet do begin
  while not Eof do begin
    if NeedProcessing then begin
      case Field1.Value of
       3: Inc(Count1);
       4: Inc(Count2);
      end;
{   ... обработка данных }
    end;
    Next;
  end;
end;
end;


 
panov ©   (2004-06-08 17:16) [23]

Непонятно, зачем усложнять?

begin
while not Eof do
begin
 case Field1.Value of
   3: if Count1<=3 then Inc(Count1);
   4: if Count2<=4 then Inc(Count2);
 else
   begin
Next;
Continue;
   end;
 end;
 ... обработка данных
 Next;
end;
end;


 
Sandman25 ©   (2004-06-08 17:19) [24]

[23] panov ©   (08.06.04 17:16)

Не эквивалентно [0]


 
Weber ©   (2004-06-08 17:20) [25]


> panov ©   (08.06.04 17:16) [23]

Вот именно, "дайте кусок вашего кода нам и через минуту вы не узнаете его!"


 
panov ©   (2004-06-08 17:24) [26]

>Sandman25 ©   (08.06.04 17:19) [24]

уг-)

достаточно 1 и 2 включить.

begin
while not Eof do
begin
case Field1.Value of
  1,2: ;
  3: if Count1<=3 then Inc(Count1);
  4: if Count2<=4 then Inc(Count2);
else
  begin
   Next;
   Continue;
  end;
end;
... обработка данных
Next;
end;
end;


 
panov ©   (2004-06-08 17:25) [27]

>Sandman25 ©   (08.06.04 17:19) [24]

Кстати, а какие критерии оптимальности?


 
Sandman25 ©   (2004-06-08 17:28) [28]

[26] panov ©   (08.06.04 17:24)

Все равно не соответствует. Не надо обрабатывать, если Count1 стала > 4 и т.д.

[27] panov ©   (08.06.04 17:25)

В первую очередь - структурность, во вторую - скорость. В третью - размер кода и данных :)


 
panov ©   (2004-06-08 17:31) [29]

>Sandman25 ©   (08.06.04 17:28) [28]

С критериями понятно-)
Тогда решения есть уже, и не одно-)


 
Игорь Шевченко ©   (2004-06-08 17:33) [30]

Sandman25 ©   (08.06.04 17:28)

Я руководствовался одним критерием - читабельность кода. И рекомендую всех руководствоваться им же :)

С этой точки зрения вариант Sandman25 ©   (08.06.04 17:11) [22]
выглядит более читабельным, чем мой.


 
Sandman25 ©   (2004-06-08 17:34) [31]

[29] panov ©   (08.06.04 17:31)

Именно так. И [1], и [20] меня вполне устраивают. Все же продолжаю читать ветку - вдруг что-нибудь новое узнаю :)


 
Anatoly Podgoretsky ©   (2004-06-08 17:36) [32]

На скорость может внимания не обращать, оно ничтожно по отношению с остальным.


 
panov ©   (2004-06-08 17:37) [33]

>Игорь Шевченко ©   (08.06.04 17:33) [30]

Разве использование case дважды улучшает читабельность кода?


 
Sandman25 ©   (2004-06-08 17:37) [34]

[30] Игорь Шевченко ©   (08.06.04 17:33)

Иногда читабельностью нужно пренебречь ради скорости. Простейший пример:

with DataSet do
 try
   while not Eof do
   begin
     Edit;
     ...
     Post;
     Next;  
   end;
 except
   if State in dsEditModes then
     Cancel;
   raise;
 end;

Читабельнее вызывать процедуру с try-except внутри, но try-except в цикле сильно затормозит работу.


 
Sandman25 ©   (2004-06-08 17:38) [35]

[32] Anatoly Podgoretsky ©   (08.06.04 17:36)

В принципе согласен, но у меня это уже дело привычки :)
Раньше отвечал за скорость работы хранимых процедур


 
panov ©   (2004-06-08 17:38) [36]

К тому же, если в [0] видна вся структура вычмслений, то в [22], чтобы понять логику, нужно еще всмотреться пристально и напрячься.


 
Verg ©   (2004-06-08 17:40) [37]

Я бы добавил к коду:


> [1] Digitman ©   (08.06.04 12:21)
> with DataSet do
> while not Eof do
>  try
>    case Field1.Value of
>      1, 2:;
>      3: if Count1 > 3 then Continue else Inc(Count1);
>      4: if Count2 > 4 then Continue else Inc(Count2);
     else
        continue;

>    end;
>   ... обработка данных
>  finally
>    Next;
>  end;


...и успокоился бы. Вызов кодом самой же программы цепочки (чек) finally - исчезающе малое время по сравнению с Next у DataSet


 
Игорь Шевченко ©   (2004-06-08 17:41) [38]


>  но try-except в цикле сильно затормозит работу.


По какой причине ?

panov ©   (08.06.04 17:38)


> К тому же, если в [0] видна вся структура вычмслений,


В [0] ее как раз и не видно


 
Sandman25 ©   (2004-06-08 17:52) [39]

Только что сделал через метку. Стошнило от одного только вида, хотя по скорости и было оптимально.
Попробовал сделать через локальную процедуру. Вроде ничего смотрится.
     case RelatedIndex of
       1,  // отец
       2:  // мать
          PrintRelated;
       3:  // супруг(и)
         begin
            Inc(MarriedCount);
            // разрешаем до 3 супругов включительно
            if MarriedCount <= 3 then
            begin
              RelatedIndex := 2 + MarriedCount; // от 3 до 5
              PrintRelated;
            end;
          end;
       4:  // дети
          begin
            Inc(ChildrenCount);
            // разрешаем до 4 детей включительно
            if ChildrenCount > 4 then
            begin
              RelatedIndex := 5 + ChildrenCount; // от 6 до 9
              PrintRelated;
            end;
          end
     end;
     clRelated.Next;


 
Sandman25 ©   (2004-06-08 17:54) [40]

[38] Игорь Шевченко ©   (08.06.04 17:41)

По причине большого числа дополнительных ассемблерных команд для обеспечения try-except.



Страницы: 1 2 вся ветка

Форум: "Основная";
Текущий архив: 2004.06.20;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.037 c
14-1085903308
KilkennyCat
2004-05-30 11:48
2004.06.20
Компонент MS Word


1-1086250968
Rulezz
2004-06-03 12:22
2004.06.20
Алгоритм


14-1085944583
Xploit
2004-05-30 23:16
2004.06.20
Настоящий OnTOP,Щелчок по заголовку колонки StringGrid, Печать


1-1086463585
san
2004-06-05 23:26
2004.06.20
Совместимость отчетов


6-1082858101
FatBase
2004-04-25 05:55
2004.06.20
Отправка почты: как всё объединить?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский