История вопроса такова, что у коллеги из смежного отдела возникла проблема с сопоставлением больших списков телефонов, обычно это делалось в Excel`е с помощью функции ВПР(), но при обработке двух списков в каждом из которых порядка миллиона строк, Excel стал просто "вешать" компьютер на час и более, хорошо если при этом удавалось дождаться результата.
Было решено сделать процедуру сравнения файлов, работающую более эффективно.
В результате была создана обработка для 1С (управляемые формы), которая читает списки телефонов из текстовых файлов, сортирует их средствами 1С и затем сравнивает: либо вычитая один список из другого, либо находит пересечение.
Версия платформы 8.3.9.2233
Режим использования модальности - не использовать
Режим совместимости - не использовать
Для чтения и записи текстовых файлов используется объект ADODB.Stream, т.к. это оказался наиболее быстрый способ из протестированных:
Чтение файла:
file = Новый COMОбъект("ADODB.Stream");
file.Type = 2;
file.charset = "windows-1251";
file.Open();
file.LoadFromFile(СокрЛП(Файл1));
й = 0;
Пока file.EOS = 0 Цикл
й = й + 1;
Если ((й % 2000) = 0) Тогда
Состояние("Чтение файла № " + Формат(ё, "ЧГ=") + ": " + Формат(й, "ЧГ="));
КонецЕсли;
ОбработкаПрерыванияПользователя();
cardnum = СокрЛП(file.ReadText(-2));
Если cardnum <> "" Тогда
сп1.Добавить(cardnum);
КонецЕсли;
КонецЦикла;
file.Close();
Запись файла:
ПС = Символ(13) + Символ(10);
file = Новый COMОбъект("ADODB.Stream");
file.Type = 2;
file.charset = "windows-1251";
file.LineSeparator = -1;
file.Open();
Для ъ = 1 по N Цикл
Если ((ъ % 500) = 0) Тогда
Состояние("Формирование строки для записи в файл: " + Формат(ъ, "ЧГ=") + " " + Формат(ъ/N*100, "ЧДЦ=2; ЧН=0; ЧГ=") + "%");
КонецЕсли;
file.WriteText(СокрЛП(м3[ъ-1]) + ПС);
КонецЦикла;
file.SaveToFile(Файл3, 2);
Обработка отсортированных массивов, алгоритм был взят с просторов интернета
Процедура ВыполнитьВычитание()
N = м1.Количество()-1;
K = м2.Количество()-1;
ъ = 0; ь = 0;
Пока (ъ <= N) и (ь <= K) Цикл
Если ((ъ % 1000) = 0) Тогда
Состояние("Обработка массивов(вычитание): " + Формат(ъ, "ЧГ=") + " " + Формат(ъ/N*100, "ЧДЦ=2; ЧН=0; ЧГ=") + "%");
КонецЕсли;
Если м1[ъ] < м2[ь] Тогда
м3.Добавить(м1[ъ]);
ъ = ъ + 1;
ИначеЕсли м1[ъ] > м2[ь] Тогда
ь = ь + 1;
Иначе
ь = ь + 1;
ъ = ъ + 1;
КонецЕсли;
КонецЦикла;
м1 = ""; м2 = "";
КонецПроцедуры
Процедура ВыполнитьПересечение()
N = м1.Количество()-1;
K = м2.Количество()-1;
ъ = 0; ь = 0;
Пока (ъ <= N) и (ь <= K) Цикл
Если ((ъ % 1000) = 0) Тогда
Состояние("Обработка массивов(пересечение): " + Формат(ъ, "ЧГ=") + " " + Формат(ъ/N*100, "ЧДЦ=2; ЧН=0; ЧГ=") + "%");
КонецЕсли;
Если м1[ъ] < м2[ь] Тогда
ъ = ъ + 1;
ИначеЕсли м1[ъ] > м2[ь] Тогда
ь = ь + 1;
Иначе
м3.Добавить(м1[ъ]);
ь = ь + 1;
ъ = ъ + 1;
КонецЕсли;
КонецЦикла;
м1 = ""; м2 = "";
КонецПроцедуры
На последнем скрине видно время обработки двух списков и их размер