Алгоритм синхронизации (сравнения) двух таблиц (по текстовому полю) (1Cv8)

Материал из КинтВики
Перейти к: навигация, поиск


Источник

Автор статьи: vde69

Редакторы: Гений 1С, Волшебник, Alter72

Последняя редакция №8 от 18.09.08

URL: http://kb.mista.ru/article.php?id=129

Ключевые слова: синхронизация, динамических, таблиц, алгоритм, сравнение, строк

v8: Алгоритм синхронизации (сравнения) двух таблиц (по текстовому полю)

В процессе обмена данными часто возникает вопрос синхронизации двух динамических таблиц по одному полю. Для небольших объемов информации вполне подходит и простой перебор всех вариантов (двойной цикл, или рекурсия). Но для больших массивов (более 10 000 элементов) это становиться очень медленно. Предлагаю использовать другой алгоритм, основанный на одном цикле, в моем случае это дало ускорение в х800!!!

Для начала рассмотрим общий принцип:

  1. Надо получить две таблицы (в моем случае ДанныеФайла и ВсеТовары), процесс получения таблиц здесь не рассматривается
  2. Предварительная обработка строк индекса, приведение к одному регистру, удаление пробелов, другое форматирование, это здесь тоже не рассматривается
  3. Сортировка таблиц по индексу
  4. Параллельная обработка двух таблиц

Теперь собственно пример:

<source lang=1c> // сравнивает по символьно строки, возвращает истина если // Строка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");
           Прервать;            
       КонецЕсли
       
   КонецЦикла;

КонецПроцедуры </source>


Вот собственно и все.

От Гения 1С: Другой вариант решения задачи здесь Книга знаний: v8: Сравнение двух таблиц значений с ключемыми полями

Вместо СтрокаБольше() можно и для строк использовать операторы сравнения (>, =, < и тд...) Принцип сравнения тот же самый, различает большие и маленькие буквы (маленькая меньше большой).