Синхронизации двух динамических таблиц по одному полю
В процессе обмена данными часто возникает вопрос синхронизации двух динамических таблиц по одному полю. Для небольших объемов информации вполне подходит и простой перебор всех вариантов (двойной цикл, или рекурсия). Но для больших массивов (более 10 000 элементов) это становиться очень медленно. Предлагаю использовать другой алгоритм, основанный на одном цикле, в моем случае это дало ускорение в х800!!!
Общий принцип:
- Надо получить две таблицы (в моем случае ДанныеФайла и ВсеТовары), процесс получения таблиц здесь не рассматривается
- Предварительная обработка строк индекса, приведение к одному регистру, удаление пробелов, другое форматирование, это здесь тоже не рассматривается
- Сортировка таблиц по индексу
- Параллельная обработка двух таблиц
Собственно пример:
// сравнивает по символьно строки, возвращает истина если // Строка1 больше чем Строка2 Функция СтрокаБольше(Строка1, Строка2) Результат = Ложь; Длина = Макс(СтрДлина(Строка1),СтрДлина(Строка2)); Для Индекс = 1 По Длина Цикл Если Индекс > СтрДлина(Строка2)Тогда // если дошли до сюда, значит строка1 длинее строки2 Результат = Истина; Прервать; ИначеЕсли Индекс > СтрДлина(Строка1)Тогда // ну а в этом случае короче, а значит меньше Результат = Ложь; Прервать; КонецЕсли; // сравнение по коду символа не работает, поэтому сравниваем по символьно // символ можно получать и по другому, // но этот вариант у меня работает быстрее Код1 = Символ(КодСимвола(Строка1, Индекс)); Код2 = Символ(КодСимвола(Строка2, Индекс)); Если Код1 < Код2 Тогда // все, дальше можно не смотреть, попался больший символ Результат = Ложь; Прервать; ИначеЕсли Код1 > Код2 Тогда // все, дальше можно не смотреть, попался меньший символ Результат = Истина; Прервать; КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции Процедура Выполнить() ВсеТовары.Сортировать ("Артикул Возр"); ДанныеФайла.Сортировать("Артикул Возр"); Результат = Новый ТаблицаЗначений; Результат.Колонки.Добавить( "Номенклатура", Справочники.Номенклатура); ИндексВсеТовары = 0; // это указатели на текущую позицию ИндексДанныеФайла = 0; Пока Истина Цикл // а вот и главный цикл ОбработкаПрерыванияПользователя( ); Попытка ЭлементВсеТовары = ВсеТовары[ИндексВсеТовары]; ЭлементДанныеФайла = ДанныеФайла[ИндексДанныеФайла]; Исключение // обработка закончена, это выход из цикла Прервать; КонецПопытки; Если ЭлементВсеТовары.Артикул = ЭлементДанныеФайла.Артикул тогда ИндексВсеТовары = ИндексВсеТовары + 1; ИндексДанныеФайла = ИндексДанныеФайла + 1; // Добавляем строку с ценой в результат НоваяСтрока = Результат.Добавить( ); НоваяСтрока.Номенклатура = ЭлементВсеТовары.Номенклатура; ИначеЕсли СтрокаБольше(ЭлементДанныеФайла.Артикул, ЭлементВсеТовары.Артикул) Тогда // Двигаем товары ИндексВсеТовары = ИндексВсеТовары + 1; ИначеЕсли СтрокаБольше(ЭлементВсеТовары.Артикул, ЭлементДанныеФайла.Артикул) Тогда // Двигаем файлы ИндексДанныеФайла = ИндексДанныеФайла + 1; Иначе // если сюда попали, значит беда (сделано только для отладки условий) Сообщить("Ошибка алгоритма 2"); Прервать; КонецЕсли КонецЦикла; КонецПроцедуры