Я создал следующую функцию, которая поддерживает конечные буквы, ведущие нули ... (см. Примеры ниже):
function cmpVersions(a, b) {
var partsA = a.split('.');
var partsB = b.split('.');
var nbParts = Math.max(partsA.length, partsB.length);
for (var i = 0; i < nbParts; ++i) {
if (partsA[i] === undefined) {
partsA[i] = '0';
}
if (partsB[i] === undefined) {
partsB[i] = '0';
}
// edit: added this part
// - fixes the important case "1.2 / 1.10"
// - but breaks the not-so-important case "1.02 / 1.1"
var intA = parseInt(partsA[i], 10);
var intB = parseInt(partsB[i], 10);
if (!isNaN(intA) && !isNaN(intB)) {
if (intA > intB) {
return 1;
} else if (intA < intB) {
return -1;
}
}
var compare = partsA[i].localeCompare(partsB[i]);
if (compare !== 0) {
return compare;
}
}
return 0;
}
Итак, несколько примеров:
// trailing letters
cmpVersion('1.0a', '1.0b'); // -1
// leading zeroes
cmpVersion('1.01', '1.1'); // -1
// "zero" parts
cmpVersion('1', '1.0'); // 0
Если вам не нужно поддерживать начальные нули, вот более простая альтернатива:
function cmpVersions(a, b) {
function padParts(version) {
return version
.split('.')
.map(function (part) {
return '00000000'.substr(0, 8 - part.length) + part;
})
.join('.');
}
a = padParts(a);
b = padParts(b);
return a.localeCompare(b);
}
Быстрое обновление: Впоследствии я заметил, что первая функция сортирует «1.2»до "1.10", что явно неправильно.Кроме того, «значимые начальные нули» хитры и неоднозначны (как для интерпретации, так и для реализации), и семантическое управление версиями явно избегает их.Поэтому я думаю, что вторая функция всегда должна быть предпочтительнее.
Обновление 2: Но вторая функция сортирует «1.2a» перед «1.1» ... Я думаю, что просто нет »одна подходит для всех "функций ... Выберите" более подходящую "функцию в соответствии с вашим вариантом использования, или, лучше, по возможности сортируйте по дате.
Обновление 3: Изменено первоефункция для правильной обработки важного случая "1.2 / 1.10".Как побочный эффект, это нарушает не столь важный случай "1.02 / 1.1", и, очевидно, это теперь единственное предупреждение (возможно, это можно исправить, но я не уверен, что оно того стоит).Поэтому сейчас я рекомендую фиксированную первую функцию.