Алгоритмы циклов для группировок Ключевые слова: алгоритмы,группировки,циклы
Часто на практике нужно обрабатывать таблицу с некоторыми группировками. Рассмотрим алгоритм получения итогов по таблице Т, сгруппированных по колонке Буква.
Таблица Т:
Буква Сумма
А 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) имеется объект ИндексированнаяТаблица - замена ТаблицыЗначений.
Помимо прочих полезных методов имеется и метод Группировать.
Обход по группировкам стал более технологичным и не сложнее Запрос.Группировка |