Книга знаний

Инф. технологии / Приемы программирования

Алгоритмы циклов для группировок

Рассмотрены различные варианты циклов для группировки данныхАвтор статьи: Гений 1С | Редакторы: jbond
Последняя редакция №2 от 21.06.06 | История
URL: http://kb.mista.ru/article.php?id=255

Ключевые слова: алгоритмы,группировки,циклы


Часто на практике нужно обрабатывать таблицу с некоторыми группировками. Рассмотрим алгоритм получения итогов по таблице Т, сгруппированных по колонке Буква.
Таблица Т:
Буква    Сумма
А    1
А    2
Б    1
Б    2

Очень часто в коде конфигураций встречается такой алгоритм:
 
Для Инд=0 по Т.Количество()-1 Цикл 
   ТекБуква=Т[Инд].Буква; 
   ТекС=Т[Инд].Сумма; 
   Если Инд=0 Тогда 
       ОбрБуква=ТекБуква; 
       С=0; ЕстьРезультат=ложь; //Инициализация С 
   КонецЕсли; 
   Если ТекБуква<>ОбрБуква Тогда 
       Если ЕстьРезультат Тогда 
           Вывести(Буква, С); //Вывод результата 
       КонецЕсли; 
       С=0; ЕстьРезультат=ложь; //Инициализация С 
   Иначе 
       С=С+ТекС;         
       ЕстьРезультат=истина; 
   КонецЕсли; 
   Если Инд=Т.Количество()-1 Тогда //Последний проход 
       Если ЕстьРезультат Тогда //Для последнего прохода 
           Вывести(Буква, С); //Вывод результата 
       КонецЕсли; 
   КонецЕсли; 
КонецЦикла 


Но его недостатками является дублирование кода инициализации С и вывода результата.
Можно попробовать другой код без дублирования:

 
Для Инд=0 по (Т.Количество()-1)+1 Цикл 
   флФиниш=Инд=Т.Количество(); 

   Если НЕ флФиниш Тогда 
       //Обработка текущей строки 
       ТекБуква=Т[Инд].Буква; 
       ТекС=Т[Инд].Сумма; 

       //Инициализация для первой строки 
       Если Инд=0 Тогда 
           ОбрБуква=ТекБуква; 
           флИнициализация=истина; 
           флВыводРезультата=ложь; 
       Иначе 
           //Проверка выхода на новый класс 
           Если ТекБуква<>ОбрБуква Тогда 
               Если ЕстьРезультат Тогда 
                   флВыводРезультата=истина; 
               КонецЕсли; 
               флИнициализация=истина; 
           КонецЕсли; 
       КонецЕсли; 
   КонецЕсли; 

   Если флВыводРезультата Тогда 
       Вывести(Буква, С); //Вывод результата 
   КонецЕсли; 

   Если Не флФиниш Тогда 

       Если флИнициализация Тогда 
           С=0; ЕстьРезультат=ложь; //Инициализация С 
       КонецЕсли; 
    
       //Обработка текущей строки 
       С=С+ТекС;         
       ЕстьРезультат=истина;     
   КонецЕсли; 

КонецЦикла 


Но на самом деле идеальным алгоритмом в данном случае будет такой:
 
Инд=0;
Пока Инд<Т.Количество() Цикл
    ОбрБуква=Т[Инд].Буква; 
    С=0; //Инициализация С 
    Пока истина цикл
        ТекС=Т[Инд].Сумма; 
        С=С+ТекС;         
        Инд=Инд+1;
        Если Инд=Т.Количество() Тогда
            Прервать;
        КонецЕсли;
        ТекБуква = Т[Инд].Буква;
        Если ТекБуква<> ОбрБуква  Тогда
            Прервать;
        КонецЕсли;
    КонецЦикла;
    Вывести(С); //Вывод результата 
КонецЦикла;


Это алгоримт с постепенным продвижением переменной цикла - простой и лаконичный.

Я сам на практике применял оба этих варианта, иногда забывая, что последний работает лучше и отлаживается проще. Склероз, увы!

Обсуждение было здесь:
v8: Теоретические изыскания по циклу с последним и первым заходом.

PS В 1С++ 2.0 (www.1cpp.ru) имеется объект ИндексированнаяТаблица - замена ТаблицыЗначений.
Помимо прочих полезных методов имеется и метод Группировать.
Обход по группировкам стал более технологичным и не сложнее Запрос.Группировка

Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика