¿Cómo puedo comparar el número de versión del software usando JavaScript? (sólo números)
Aquí está el número de versión del software:
"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"
¿Cómo puedo comparar esto?
Supongamos que el orden correcto es:
"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"
La idea es simple...: Leer el primer dígito, luego el segundo, después el tercero... Pero no puedo convertir el número de versión a número flotante... También puedes ver el número de versión así:
"1.0.0.0", "1.0.1.0", "2.0.0.0", "2.0.0.1", "2.0.1.0"
Y esto queda más claro al ver cuál es la idea detrás... Pero, ¿cómo puedo convertirlo en un programa de ordenador?
sembrar
El analizador de versiones semánticas utilizado por npm.
$ npm install semver
var semver = require('semver');
semver.diff('3.4.5', '4.3.7') //'major'
semver.diff('3.4.5', '3.3.7') //'minor'
semver.gte('3.4.8', '3.4.7') //true
semver.ltr('3.4.8', '3.4.7') //false
semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
semver.clean(' =v1.2.3 ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true
var versions = [ '1.2.3', '3.4.5', '1.0.2' ]
var max = versions.sort(semver.rcompare)[0]
var min = versions.sort(semver.compare)[0]
var max = semver.maxSatisfying(versions, '*')
Enlace de versiones semánticas :
https://www.npmjs.com/package/semver#prerelease-identifiers
La idea básica para hacer esta comparación sería usar Array.split
para obtener matrices de partes de las cadenas de entrada y luego comparar pares de partes de las dos matrices; si las partes no son iguales sabemos cuál versión es más pequeña.
Hay algunos detalles importantes a tener en cuenta:
- ¿Cómo se deben comparar las partes de cada par? La pregunta quiere comparar numéricamente, pero ¿qué pasa si tenemos cadenas de versión que no están compuestas solo por dígitos (por ejemplo, "1.0a")?
- ¿Qué debería pasar si una cadena de versión tiene más partes que la otra? Lo más probable es que "1.0" deba considerarse inferior a "1.0.1", pero ¿qué pasa con "1.0.0"?
Aquí está el código para una implementación que puede usar directamente ( esencial con documentación ):
function versionCompare(v1, v2, options) {
var lexicographical = options && options.lexicographical,
zeroExtend = options && options.zeroExtend,
v1parts = v1.split('.'),
v2parts = v2.split('.');
function isValidPart(x) {
return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
}
if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
return NaN;
}
if (zeroExtend) {
while (v1parts.length < v2parts.length) v1parts.push("0");
while (v2parts.length < v1parts.length) v2parts.push("0");
}
if (!lexicographical) {
v1parts = v1parts.map(Number);
v2parts = v2parts.map(Number);
}
for (var i = 0; i < v1parts.length; ++i) {
if (v2parts.length == i) {
return 1;
}
if (v1parts[i] == v2parts[i]) {
continue;
}
else if (v1parts[i] > v2parts[i]) {
return 1;
}
else {
return -1;
}
}
if (v1parts.length != v2parts.length) {
return -1;
}
return 0;
}
Esta versión compara piezas de forma natural , no acepta sufijos de caracteres y considera que "1.7" es más pequeño que "1.7.0". El modo de comparación se puede cambiar a lexicográfico y las cadenas de versiones más cortas se pueden rellenar con ceros automáticamente utilizando el tercer argumento opcional.
Hay un JSFiddle que ejecuta "pruebas unitarias" aquí ; Es una versión ligeramente ampliada del trabajo de Ripper234 (gracias).
Nota importante: este código utiliza Array.map
y Array.every
, lo que significa que no se ejecutará en versiones de IE anteriores a la 9. Si necesita admitirlas, deberá proporcionar polyfills para los métodos que faltan.