В процессе разработки и поддержки систем на платформе 1С:Предприятие часто возникает задача сравнения номеров версий. Номера версий обычно хранятся в виде строк, например, "2.34.4", "2.35" или "11.0.1.5". Простая попытка сравнить такие строки «в лоб» операторами > или < часто приводит к логическим ошибкам. Например, строка "2.10" будет считаться меньше, чем "2.2", потому что при посимвольном сравнении единица во втором сегменте меньше двойки. В этой статье мы подробно разберем, как правильно реализовать алгоритм сравнения и выстроить версии по порядку.
Прежде чем переходить к коду, выясним причину, по которой обычное сравнение строк не работает для версий. Рассмотрим две версии: "2.4.5" и "2.10.1". Человеку понятно, что десятая минорная версия новее четвертой. Однако компьютер сравнивает символы слева направо: "2" равно "2", точка равна точке, а затем сравниваются символы "4" и "1". Так как единица меньше четверки, платформа вернет результат, что "2.10.1" меньше "2.4.5". Чтобы этого избежать, нам нужно привести сегменты версий к единому виду или сравнивать их как числа.
Один из самых простых и эффективных методов — привести каждый сегмент версии к фиксированной длине. Если мы договоримся, что каждый сегмент (число между точками) будет занимать, например, 4 символа, то версия "2.34.4" превратится в "0002.0034.0004", а "2.35" в "0002.0035.0000". Такие строки уже можно корректно сравнивать стандартными операторами.
Рассмотрим функцию, которая выполняет подобную нормализацию:
Функция НормализоватьВерсию(Знач ИсходнаяВерсия) Экспорт
// Убираем лишние пробелы
ИсходнаяВерсия = СокрЛП(ИсходнаяВерсия);
// Разделяем строку на сегменты по точке
МассивСегментов = СтрРазделить(ИсходнаяВерсия, ".");
НовыйМассив = Новый Массив;
Для Каждого Сегмент Из МассивСегментов Цикл
// Дополняем каждый сегмент нулями слева до 4-х знаков
НормализованныйСегмент = Прав("0000" + СокрЛП(Сегмент), 4);
НовыйМассив.Добавить(НормализованныйСегмент);
КонецЦикла;
// Собираем обратно в строку для удобства сравнения
Возврат СтрСоединить(НовыйМассив, ".");
КонецФункции
После такой обработки версии можно просто складывать в список значений или таблицу и использовать стандартный метод Сортировать().
Если мы не хотим модифицировать строки, мы можем реализовать функцию сравнения, которая разбивает версии на части и сравнивает их последовательно как числа. Этот метод считается более профессиональным и гибким, так как он не зависит от фиксированной длины сегмента.
Проанализируем алгоритм сравнения двух версий:
Функция СравнитьВерсии(Знач Версия1, Знач Версия2) Экспорт
Массив1 = СтрРазделить(Версия1, ".");
Массив2 = СтрРазделить(Версия2, ".");
КоличествоСегментов = Макс(Массив1.Количество(), Массив2.Количество());
Для Индекс = 0 По КоличествоСегментов - 1 Цикл
// Если сегмент отсутствует в одной из версий, считаем его равным 0
Число1 = 0;
Если Индекс < Массив1.Количество() Тогда
Число1 = Число(Массив1[Индекс]);
КонецЕсли;
Число2 = 0;
Если Индекс < Массив2.Количество() Тогда
Число2 = Число(Массив2[Индекс]);
КонецЕсли;
Если Число1 > Число2 Тогда
Возврат 1; // Первая версия новее
ИначеЕсли Число1 < Число2 Тогда
Возврат -1; // Вторая версия новее
КонецЕсли;
КонецЦикла;
Возврат 0; // Версии идентичны
КонецФункции
Данный метод учитывает ситуацию, когда версии имеют разное количество сегментов (например, "2.35" и "2.35.1"). В этом случае "2.35" будет трактоваться как "2.35.0".
Если ваша конфигурация разработана на базе Библиотеки стандартных подсистем (БСП), вам не нужно изобретать велосипед. Разработчики 1С уже предусмотрели готовые инструменты в общем модуле ОбщегоНазначенияКлиентСервер.
Рассмотрим использование функции СравнитьВерсии из БСП:
// Пример использования в коде
Результат = ОбщегоНазначенияКлиентСервер.СравнитьВерсии("2.34.6", "2.35");
Если Результат < 0 Тогда
Сообщить("Версия 2.35 новее");
ИначеЕсли Результат > 0 Тогда
Сообщить("Версия 2.34.6 новее");
Иначе
Сообщить("Версии одинаковы");
КонецЕсли;
Использование функций БСП является лучшей практикой, так как этот код оптимизирован, протестирован на различных форматах версий и учитывает все нюансы платформы.
Когда у нас есть механизм сравнения, выстроить список версий от старой к новой не составит труда. Рассмотрим самый простой способ с использованием ТаблицыЗначений, который позволяет избежать написания сортировки «пузырьком» вручную.
Разберем по шагам:
ТаблицаЗначений с двумя колонками: ИсходнаяВерсия и СортировочныйКлюч.Сортировать("СортировочныйКлюч Возр").
Процедура ВыстроитьПоПорядку(МассивВерсий)
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Версия");
ТЗ.Колонки.Добавить("Ключ");
Для Каждого ТекВерсия Из МассивВерсий Цикл
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Версия = ТекВерсия;
НоваяСтрока.Ключ = НормализоватьВерсию(ТекВерсия); // Используем функцию из Решения 1
КонецЦикла;
ТЗ.Сортировать("Ключ Возр");
Для Каждого Стр Из ТЗ Цикл
Сообщить(Стр.Версия);
КонецЦикла;
КонецПроцедуры
Мы проанализировали три способа решения задачи. Нормализация строк удобна для быстрой сортировки в таблицах и списках. Посегментное сравнение более гибкое и не требует изменения данных. А использование стандартных функций БСП — самый надежный и быстрый путь для профессионального разработчика.
Важно помнить, что в некоторых системах версионирования могут встречаться не только цифры, но и суффиксы (например, "RC", "beta"). В таких случаях алгоритм усложняется, но для стандартных номеров конфигураций 1С описанных выше методов более чем достаточно.