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