Czy ktoś ma kod, aby porównać dwie numery wersji w JavaScript? Chcę tylko porównania prostej wersji (np "1.0" vs {x1}}) i powinno działać z liczbami lub strunami. Może ignorować ciągnące identyfikatory beta, takie jak "1.5.6b4", ale w przeciwnym razie można oczekiwać dobrze uformowanego. Funkcja powinna zwrócić podpisaną liczbę całkowitą jak normalna funkcja CMP.

function cmpVersion(a, b)
  return less than one if a < b
  return 0 if a == b
  return greater than one if a > b

Mam odpowiedź, ale wybierze lepsze lub bardziej eleganckie rozwiązanie na własną rękę.

(Używam tego do porównania numerów jQuery.browser.version, ale odpowiedź będzie bardziej stosowana)

9
theazureshadow 10 październik 2011, 22:37

7 odpowiedzi

Najlepsza odpowiedź
function cmpVersion(a, b) {
    var i, cmp, len;
    a = (a + '').split('.');
    b = (b + '').split('.');
    len = Math.max(a.length, b.length);
    for( i = 0; i < len; i++ ) {
        if( a[i] === undefined ) {
            a[i] = '0';
        }
        if( b[i] === undefined ) {
            b[i] = '0';
        }
        cmp = parseInt(a[i], 10) - parseInt(b[i], 10);
        if( cmp !== 0 ) {
            return (cmp < 0 ? -1 : 1);
        }
    }
    return 0;
}

function gteVersion(a, b) {
    return cmpVersion(a, b) >= 0;
}
function ltVersion(a, b) {
    return cmpVersion(a, b) < 0;
}

Ta funkcja obsługuje:

  • Liczby lub ciągi jako wejście
  • Trailing zera (np cmpVersion("1.0", 1) zwraca 0)
  • ignoruje ciągnące alpha, b, pre4 itp
14
theazureshadow 3 lipiec 2018, 17:34

Jeśli chcesz być w pełni poprawny, spójrz na dyskusję na temat pep386, zwłaszcza nagłówek "Nowy algorytm wersji".

W przeciwnym razie wydaje się, że twoja odpowiedź jest całkiem dobra.

5
David Wolever 10 październik 2011, 18:43

NPM korzysta z ładnej składni do porównania wersji i możesz uzyskać ten sam moduł tutaj: https://github.com/ Isaacs / Node-Semver

Obsługiwane są następujące style zasięgu:

  • 1.2.3 Wersja określona. Kiedy nic innego zrobi. Należy pamiętać, że budowa metadane jest nadal ignorowana, więc 1.2.3+build2012 spełni ten zakres.
  • >1.2.3 większa niż określona wersja.
  • <1.2.3 Mniej niż określona wersja. Jeśli w zakresie wersji nie ma znacznika prerelease, żadna wersja prerease nie będzie dozwolona, mimo że są to technicznie "mniej niż".
  • >=1.2.3 większa lub równa. Należy pamiętać, że wersje prerease nie są równe ich "normalne" odpowiedniki, więc 1.2.3-beta nie spełniają tego zakresu, ale 2.3.0-beta będzie.
  • <=1.2.3 mniejszy lub równy. W takim przypadku dozwolone są wersje prerease, więc 1.2.3-beta spełniałyby.
  • 1.2.3 - 2.3.4: = {x1}}
  • ~1.2.3: = {x1}} "Rozsądnie blisko 1,2,3". Podczas korzystania z operatorów Tilde, wersje Prereazy są również obsługiwane, ale prerease kolejnej znaczącej cyfry nie będzie zadowalające, więc 1.3.0-beta nie spełnia ~1.2.3.
  • ^1.2.3: = {X1}} "Kompatybilny z 1.2.3". Podczas korzystania z operatorów CARET, wszystko z określonej wersji (w tym prerelease) będzie obsługiwane, ale nie włącznie, kolejna główna wersja (lub jego prerelacje). 1.5.1 spełnia ^1.2.3, podczas gdy 1.2.2 i 2.0.0-beta nie.
  • ^0.1.3: = {X1}} "Kompatybilny z 0.1.3". 0.x.x Wersje są specjalne: Pierwszy składnik niezerowy wskazuje potencjalnie łamanie zmian, co oznacza, że operator CARET pasuje do dowolnej wersji z tym samym pierwszym składnikiem niezerowym zaczynającym od określonej wersji.
  • ^0.0.2: = {X1}} "Tylko wersja 0.0.2 jest uważana za zgodną"
  • ~1.2: = {x1}} "Każda wersja począwszy od 1,2"
  • ^1.2: = {x1}} "Każda wersja kompatybilna z 1.2"
  • 1.2.x: = {x1}} "Każda wersja począwszy od 1,2"
  • ~1: = {x1}} "Każda wersja począwszy od 1"
  • ^1: = {x1}} "Każda wersja kompatybilna z 1"
  • 1.x: = {x1}} "Każda wersja począwszy od 1"

Zakresy można dołączyć do przestrzeni (która implikuje "i") lub || (co oznacza "lub").

3
laktak 15 grudzień 2013, 18:14
function compareVersion(a, b) {
    return compareVersionRecursive(a.split("."), b.split("."));
}

function compareVersionRecursive(a, b) {
    if (a.length == 0) {
        a = [0];
    }
    if (b.length == 0) {
        b = [0];
    }
    if (a[0] != b[0] || (a.length == 1 && b.length == 1)) {
        return a[0] - b[0];
    }
    return compareVersionRecursive(a.slice(1), b.slice(1));
}
0
golf 10 październik 2011, 19:10

Odkształciłem się, by być tak zwięzłym, jak mogę to zrobić. Nie ma czeku do ciągnięcia zera, ale będzie działać w celu budowania liczb dowolnej długości (np. Major, Major.minor, Major.minor.Build).

var cmpVersion = function(a, b) {
  let arrA = Array.from(a.split('.'), i => +i);
  let arrB = Array.from(b.split('.'), i => +i);

  for (let i = 0; i < (arrA.length >= arrB.length ? arrA.length : arrB.length); i++) {
    if (arrA[i] && !arrB[i] || arrA[i] > arrB[i]) return 'less than one';
    else if (!arrA[i] && arrB[i] || arrA[i] < arrB[i]) return 'greater than one';
  }
  return 0;
}

Zasadniczo, najpierw stworzyłem nową tablicę z każdego ciągu wersji, aby można było porównać każdą cyfrę indywidualnie. Następnie w pętli, wybieram długość najdłuższego ciągu wersji (lub długości pierwszej wersji łańcucha, jeśli są o równej długości).

W przypadku sprawdza oświadczenie, czy istnieje cyfra w A, ale nie w B lub jeśli cyfra A jest większa niż cyfra B dla odpowiedniego zastępczego, w którym to przypadku zwróci "mniej niż jeden".

Podobnie jak inaczej instrukcja sprawdza, czy istnieje cyfra w B, ale nie w A lub jeśli cyfra B jest większa niż cyfra a dla odpowiedniej wartości miejsca, w którym to przypadku powróci "większy niż jeden" .

Ostatni stwierdzenie zwrotu 0 to złapanie - wszystko, co nasza funkcja dostanie się, jeśli struny wersji są równe.

0
Jordan Stubblefield 4 lipiec 2017, 04:09

Jeśli nie dbasz o .5.6, użyj Parseint

var majorV = parseInt("1.5.6",10)

Odkąd powiedziałeś, że zależy Ci na drobnych wersjach:

function cmpVersion(v1, v2) {
    if(v1===v2) return 0;
    var a1 = v1.toString().split(".");
    var a2 = v2.toString().split(".");
    for( var i = 0; i < a1.length && i < a2.length; i++ ) {
        var diff = parseInt(a1[i],10) - parseInt(a2[i],10);
        if( diff>0 ) {
            return 1;
        }
        else if( diff<0 ) {
            return -1;
        }
    }
    diff = a1.length - a2.length;
    return (diff>0) ? 1 : (diff<0) ? -1 : 0;
}

console.log( cmpVersion( "1.0", "1.56") );
console.log( cmpVersion( "1.56", "1.56") );
console.log( cmpVersion( "1.65", "1.5.6") );
console.log( cmpVersion( "1.0", "1.5.6b3") );
-1
epascarello 10 październik 2011, 18:58

Ta funkcja zwraca wartość true, jeśli wersja jest większa lub równa wersji minimalnej. Zakłada 1.0 jest większa niż 1, gdy wersje są ciążem. Kiedy są liczbami, mówi, że są takie same. Jeśli chcesz mieć oba typy, powrócą tak samo, musisz przekonwertować liczby do ciągów, które są również łatwe. Albo możesz zmodyfikować warunek łańcuchowy, aby sprawdzić, czy dłuższy numer wersji ma wszystkie zera, takie jak 1.1 vs 1.1.0.0.0.0. Drugi to wszystko kończą się zerami

 function doesMyVersionMeetMinimum(myVersion, minimumVersion) {

    if(typeof myVersion === 'number' && typeof minimumVersion === 'number') {
      return(myVersion >= minimumVersion);
    }

    var v1 = myVersion.split("."), v2 = minimumVersion.split("."), minLength;

    minLength= Math.min(v1.length, v2.length);

    for(i=0; i<minLength; i++) {
        if(Number(v1[i]) < Number(v2[i])) {
            return false;
        }
       else if(Number(v1[i]) < Number(v2[i])) {
            return true;
        }           

    }

    return (v1.length >= v2.length);
}
-1
Will Schulz 17 luty 2016, 19:23