Еще один (:-)) простейший алгоритм определения итогов по группировкам для произвольных таблиц значений.
16.01.09
Разработка - Математика и алгоритмы
Простой и быстрый алгоритм получения итогов по произвольному числу группировок таблицы значений.
Еще один (:-)) простейший алгоритм определения итогов по группировкам для произвольных таблиц значений.
Обозначенная выше задача, увы, не блещет оригинальностью – с подобной задачей рано или поздно сталкивается любой 1С-ник, более того даже на данном сайте можно найти не менее десятка вариантов решения указанной проблемы. Тем не менее какого-либо общего, всеми признанного по красоте и скорости решения данной задачи нет до сих пор (если, конечно, не говорить об использовании внешних компонент). Поэтому автор не считает зазорным оказаться в длинной очереди изобретателей жаждущих зарегистрировать свое рацпредложение :-).
Приведу суть алгоритма на простейшем примере. Допустим, что мы имеем таблицу значений с нечисловыми колонками "А", "Б", "В" и "Г" и некоторым количеством числовых колонок, пусть это будут колонки "Сумма1", "Сумма2", "Сумма3" (считаем, что порядок колонок в ТЗ соответствует порядку их перечисления, для рассматриваемого алгоритма этот порядок важен. Кроме того крайне желательно, чтобы колонки были типизированы). Будем считать, что перед нами стоит задача определения итоговых сумм числовых колонок по группировкам "А" и "Б" соответственно.
Добавим в уже существующую таблицу колонку "Уровень":
Будем считать, что данные необработанной таблицы соответствуют третьему уровню, тогда как данные группировок – уровням 1 и 2.
Создадим копию имеющейся таблицы:
Если скорость выполнения задачи критична, можно скопировать ТЗ с помощью команды Заполнить.
Определим дополнительные строки ТЗ, которые соответствуют второму уровню, для этого свернем ТЗДоп:
Здесь необходимо заметить, что порядок колонок в операторе Заполнить должен совпадать с порядком колонок в ТЗДоп, в противном случае результат окажется некорректен.
То же самое проделаем для определения группировок первого уровня:
Наконец, для определения окончательного результата достаточно отсортировать полученную ТЗ:
Замечу, что сортировка по внутренним представлениям включена для того, чтобы система не путала различные элементы с одинаковыми наименованиями. В этом и заключается самый главный недостаток предложенного метода – для сортировки по наименованиям сформированную ТЗ надо будет еще обрабатывать, если же сортировка ТЗ не является критичной или же можно отсортировать сразу по наименованию без вероятности перепутывания элементов то результат, полученный на этом шаге готов к дальнейшему использованию.
Обозначенная выше задача, увы, не блещет оригинальностью – с подобной задачей рано или поздно сталкивается любой 1С-ник, более того даже на данном сайте можно найти не менее десятка вариантов решения указанной проблемы. Тем не менее какого-либо общего, всеми признанного по красоте и скорости решения данной задачи нет до сих пор (если, конечно, не говорить об использовании внешних компонент). Поэтому автор не считает зазорным оказаться в длинной очереди изобретателей жаждущих зарегистрировать свое рацпредложение :-).
Приведу суть алгоритма на простейшем примере. Допустим, что мы имеем таблицу значений с нечисловыми колонками "А", "Б", "В" и "Г" и некоторым количеством числовых колонок, пусть это будут колонки "Сумма1", "Сумма2", "Сумма3" (считаем, что порядок колонок в ТЗ соответствует порядку их перечисления, для рассматриваемого алгоритма этот порядок важен. Кроме того крайне желательно, чтобы колонки были типизированы). Будем считать, что перед нами стоит задача определения итоговых сумм числовых колонок по группировкам "А" и "Б" соответственно.
Добавим в уже существующую таблицу колонку "Уровень":
ТЗ.НоваяКолонка("Уровень","Число",9,0);
Будем считать, что данные необработанной таблицы соответствуют третьему уровню, тогда как данные группировок – уровням 1 и 2.
ТЗ.Заполнить(3,,, "Уровень");
Создадим копию имеющейся таблицы:
ТЗДоп = СоздатьОбъект("ТаблицаЗначений"); ТЗ.Выгрузить(ТЗДоп);
Если скорость выполнения задачи критична, можно скопировать ТЗ с помощью команды Заполнить.
Определим дополнительные строки ТЗ, которые соответствуют второму уровню, для этого свернем ТЗДоп:
ТЗДоп.Свернуть("А,Б","Сумма1,Сумма2,Сумма3");Поскольку при свертке ТЗДоп колонка "Уровень" была уничтожена добавим ее:
ТЗДоп.НоваяКолонка("Уровень", "Число", 9,0);Получили результаты второго уровня:
ТЗДоп.Заполнить(2,,, "Уровень");
Добавим полученные результаты к первоначальной ТЗ следующим образом:
ВсегоСтрокВТЗ = ТЗ.КоличествоСтрок(); ВсегоСтрокВТЗДоп = ТЗДоп.КоличествоСтрок(); ТЗ.КоличествоСтрок(ВсегоСтрокВТЗ + ВсегоСтрокВТЗДоп); ТЗ.Заполнить(ТЗДоп,(ВсегоСтрокВТЗ + 1), (ВсегоСтрокВТЗ + ВсегоСтрокВТЗДоп), "А,Б,Сумма1,Сумма2,Сумма3,Уровень");
Здесь необходимо заметить, что порядок колонок в операторе Заполнить должен совпадать с порядком колонок в ТЗДоп, в противном случае результат окажется некорректен.
То же самое проделаем для определения группировок первого уровня:
ТЗДоп.Свернуть("А", "Сумма1,Сумма2,Сумма3"); ТЗДоп.НоваяКолонка("Уровень", "Число", 9, 0); ТЗДоп.Заполнить(1,,,"Уровень"); ВсегоСтрокВТЗ = ТЗ.КоличествоСтрок(); ВсегоСтрокВТЗДоп = ТЗДоп.КоличествоСтрок(); ТЗ.КоличествоСтрок(ВсегоСтрокВТЗ + ВсегоСтрокВТЗДоп); ТЗ.Заполнить(ТЗДоп,(ВсегоСтрокВТЗ + 1), (ВсегоСтрокВТЗ + ВсегоСтрокВТЗДоп), "А,Сумма1,Сумма2,Сумма3,Уровень")
Наконец, для определения окончательного результата достаточно отсортировать полученную ТЗ:
ТЗ.Сортировать("*А,*Б,Уровень");
Замечу, что сортировка по внутренним представлениям включена для того, чтобы система не путала различные элементы с одинаковыми наименованиями. В этом и заключается самый главный недостаток предложенного метода – для сортировки по наименованиям сформированную ТЗ надо будет еще обрабатывать, если же сортировка ТЗ не является критичной или же можно отсортировать сразу по наименованию без вероятности перепутывания элементов то результат, полученный на этом шаге готов к дальнейшему использованию.
Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.