Comment puis-je comparer les numéros de version arbitraires?

Quelqu'un at-il un code pour comparer deux numéros de version en JavaScript? Je veux juste des comparaisons de versions simples (p. Ex. "1.0" vs "1.5.6" ), et cela devrait fonctionner avec des nombres ou des chaînes. Il peut ignorer les identificateurs bêta suivants comme "1.5.6b4" , mais on peut s'attendre à ce que les chaînes soient bien formées. La fonction doit renvoyer un entier signé comme une fonction cmp normale.

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

J'ai une réponse, mais je choisirai une solution meilleure ou plus élégante sur la mienne.

(J'utilise ceci pour comparer les nombres de jQuery.browser.version , mais la réponse sera plus largement applicable)

 function cmpVersion(a, b) { var i, cmp, len, re = /(\.0)+[^\.]*$/; a = (a + '').replace(re, '').split('.'); b = (b + '').replace(re, '').split('.'); len = Math.min(a.length, b.length); for( i = 0; i < len; i++ ) { cmp = parseInt(a[i], 10) - parseInt(b[i], 10); if( cmp !== 0 ) { return cmp; } } return a.length - b.length; } function gteVersion(a, b) { return cmpVersion(a, b) >= 0; } function ltVersion(a, b) { return cmpVersion(a, b) < 0; } 

Cette fonction gère:

  • Des nombres ou des chaînes comme entrée
  • Zéros de fuite (p.ex. cmpVersion("1.0", 1) renvoie 0 )
  • pre4 alpha , b , pre4 , etc.

Si vous voulez être entièrement correct, consultez la discussion sur PEP386 , en particulier l'en-tête "le nouvel algorithme de version".

Sinon, il semble que votre réponse soit très bonne.

Npm utilise une belle syntaxe pour comparer les versions et vous pouvez obtenir le même module ici: https://github.com/isaacs/node-semver

Les styles de gamme suivants sont pris en charge:

  • 1.2.3 Une version spécifique. Quand rien d'autre ne le fera. Notez que les métadonnées de construction sont toujours ignorées, donc 1.2.3+build2012 satisfera cette gamme.
  • >1.2.3 Plus qu'une version spécifique.
  • <1.2.3 Moins qu'une version spécifique. S'il n'y a pas d'étiquette de pré-lancement sur la gamme de versions, aucune version de pré-lancement ne sera autorisée, même si cela est techniquement "inférieur à".
  • >=1.2.3 Plus grand ou égal à. Notez que les versions de préréglage ne sont PAS égales à leurs équivalents "normaux", donc 1.2.3-beta ne satisfont pas cette plage, mais 2.3.0-beta sera.
  • <=1.2.3 Moins ou égal à. Dans ce cas, les versions pré-libération sont autorisées, donc 1.2.3-beta satisfait.
  • 1.2.3 - 2.3.4 : = >=1.2.3 <=2.3.4
  • ~1.2.3 : = >=1.2.3-0 <1.3.0-0 "Raisonnablement proche de 1.2.3". Lors de l'utilisation des opérateurs tilde, les versions préréglées sont également prises en charge, mais un pré-relèvement du prochain chiffre significatif NE 1.3.0-beta PAS satisfaisant, donc 1.3.0-beta ne satisfera pas ~1.2.3 .
  • ^1.2.3 : = >=1.2.3-0 <2.0.0-0 "Compatible avec 1.2.3". Lors de l'utilisation des opérateurs de caret, tout ce qui provient de la version spécifiée (y compris le pré-relâchement) sera pris en charge jusqu'à la prochaine version majeure (ou ses pré-étapes), mais pas incluses. 1.5.1 satisfait ^1.2.3 , tandis que 1.2.2 et 2.0.0-beta ne le feront pas.
  • ^0.1.3 : = >=0.1.3-0 <0.2.0-0 "Compatible avec 0.1.3". Les versions 0.xx sont spéciales: la première composante non nulle indique des modifications potentiellement brèves, c'est-à-dire que l'opérateur de caret correspond à n'importe quelle version avec la même première composante non nulle à partir de la version spécifiée.
  • ^0.0.2 : = =0.0.2 "Seule la version 0.0.2 est considérée comme compatible"
  • ~1.2 : = >=1.2.0-0 <1.3.0-0 "Toute version commençant par 1.2"
  • ^1.2 : = >=1.2.0-0 <2.0.0-0 "Toute version compatible avec 1.2"
  • 1.2.x : = >=1.2.0-0 <1.3.0-0 "Toute version commençant par 1.2"
  • ~1 : = >=1.0.0-0 <2.0.0-0 "Toute version commençant par 1"
  • ^1 : = >=1.0.0-0 <2.0.0-0 "Toute version compatible avec 1"
  • 1.x : = >=1.0.0-0 <2.0.0-0 "Toute version commençant par 1"

Les plages peuvent être associées à un espace (ce qui implique "et") ou un || (Ce qui implique "ou").

Si vous ne vous occupez pas du .5.6, utilisez l' option ParseInt

 var majorV = parseInt("1.5.6",10) 

Puisque vous avez dit que vous vous souciez des versions mineures:

 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") ); 
 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)); } 

J'ai refacturé les mines pour être aussi concises que possible. Il n'a pas la vérification des zéros de fin de course, mais fonctionnera pour générer des nombres de toute longueur (p. Ex. Majeur, majeur, mineur, majeur.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; } 

Fondamentalement, j'ai d'abord créé un nouveau réseau hors de chaque chaîne de version afin que je puisse comparer chaque chiffre individuellement. Ensuite, dans la boucle for, je choisis la longueur de la chaîne de la version la plus longue (ou la longueur de la chaîne de la première version si elles sont d'une longueur égale).

La déclaration if vérifie s'il existe un chiffre dans a, mais pas en b, ou si le chiffre de a est supérieur au chiffre de b pour un espace réservé correspondant, auquel cas il renverra moins d'un.

De plus, l'instruction else vérifie s'il existe un chiffre dans b mais pas dans a ou si le chiffre de b est supérieur au chiffre de a pour une valeur de place correspondante, auquel cas il renverra plus de un .

La déclaration du dernier retour 0 est un catch-all, que notre fonction atteindra si les chaînes de version sont égales.

Cette fonction renvoie true si la version est supérieure ou égale à la version minimale. Supposons que 1.0 soit supérieur à 1 lorsque les versions sont des chaînes. Quand ils sont des nombres, ils disent qu'ils sont les mêmes. Si vous souhaitez que les deux types renvoient, vous devez convertir les nombres en cordes, ce qui est également facile. Ou vous pouvez modifier la condition de la chaîne pour vérifier si le numéro de version plus long contient tous les zéros de départ comme 1.1 vs 1.1.0.0.0.0. Le second est tous des zéros

  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); }