Mam spreparowane następującą funkcję, która wspiera końcowe liter początkowych zer ... (patrz przykłady poniżej):
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;
}
Tak, kilka przykładów:
// trailing letters
cmpVersion('1.0a', '1.0b'); // -1
// leading zeroes
cmpVersion('1.01', '1.1'); // -1
// "zero" parts
cmpVersion('1', '1.0'); // 0
Jeśli don Konieczne jest wsparcie wiodących zer, oto prostsza alternatywa:
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);
}
Szybka aktualizacja: Zauważyłem potem, że pierwsza funkcja sortuje "1.2" przed "1.10", co jest rażąco błędne. Ponadto "znaczące wiodące zera" są trudne i niejednoznaczne (zarówno do interpretacji, jak i do implementacji), a edycja semantyczna wyraźnie ich unika. Dlatego uważam, że druga funkcja powinna być zawsze preferowana.
Aktualizacja 2: Ale rodzaju druga funkcja „1.2a” przed „1.1” ... Myślę, że po prostu nie ma „jeden dla wszystkich” funkcji ... Pick „bardziej odpowiedni” działa zgodnie z Użyj przypadku, lub lepiej, sortuj według daty, jeśli możesz.
Aktualizacja 3: Zmodyfikowano pierwszą funkcję do prawidłowego obchodzenia się z ważnym przypadkiem "1.2/1.10". Efektem ubocznym jest przełamanie nieistotnego przypadku "1.02/1.1" i najwyraźniej jest to obecnie jedyne zastrzeżenie (może uda się je naprawić, ale nie jestem pewien, czy warto). Dlatego teraz polecam stałą, pierwszą funkcję.
Wyrecytowanie przekształciłoby" 1.02 "na" 1 ", więc' cmpVersion ('1.01', '1.02') 'daje błędny wynik. –
Edytowałem kod tej odpowiedzi za pomocą nowej metody, która rozwiązuje powyższy problem. Recenzje byłyby bardzo mile widziane, zwłaszcza w celu zauważenia jakichkolwiek regresji. Nawiasem mówiąc, ten kod nadal nie obsługuje 'cmpVersion ('1.2alpha4', '1.2alpha5')', ale myślę, że byłoby to bardziej skomplikowane do wdrożenia. –