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