Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.06.20;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.037 c
14-1085944450
Тимур
2004-05-30 23:14
2004.06.20
Game Shark


1-1086192848
Damager
2004-06-02 20:14
2004.06.20
Как переименовать папку


14-1086207122
Константинов
2004-06-03 00:12
2004.06.20
Вопрос геймерам


3-1085646446
AlexXn
2004-05-27 12:27
2004.06.20
BDE


1-1086542896
lena19
2004-06-06 21:28
2004.06.20
как получить из полного пути, имя вайла и его расширение