Синхронизации двух динамических таблиц по одному полю

В процессе обмена данными часто возникает вопрос синхронизации двух динамических таблиц по одному полю. Для небольших объемов информации вполне подходит и простой перебор всех вариантов (двойной цикл, или рекурсия). Но для больших массивов (более 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;
        Иначе
            // если сюда попали, значит беда (сделано только для отладки условий)
            Сообщить("Ошибка алгоритма 2");
            Прервать;            
        КонецЕсли
 
    КонецЦикла;
КонецПроцедуры