Wie vergleiche ich die Versionsnummer der Software mit js? (nur Nummer)

164

Hier ist die Versionsnummer der Software:

"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"

Wie kann ich das vergleichen? Angenommen, die richtige Reihenfolge ist:

"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"

Die Idee ist einfach ...: Lesen Sie die erste Ziffer, dann die zweite, danach die dritte ... Aber ich kann die Versionsnummer nicht in eine Float-Nummer umwandeln ... Sie können auch die Versionsnummer wie sehen Dies:

"1.0.0.0", "1.0.1.0", "2.0.0.0", "2.0.0.1", "2.0.1.0"

und das ist klarer zu sehen, was die Idee dahinter steckt ... Aber wie kann man es in ein Computerprogramm umwandeln? Hat jemand eine Idee, wie man das sortiert? Danke dir.

Tattat
quelle
5
Dies wäre eine gute Interviewfrage vom Typ Fizzbuzz.
Steve Claridge
2
Aus diesem Grund sollten alle Softwareversionsnummern Ganzzahlen wie 2001403 sein. Wenn Sie sie auf eine benutzerfreundliche Weise wie "2.0.14.3" anzeigen möchten, formatieren Sie die Versionsnummer zur Präsentationszeit.
Jarmod
2
Das allgemeine Problem hierbei sind Vergleiche der semantischen Version, und es ist nicht trivial (siehe Nr. 11 auf semver.org ). Glücklicherweise gibt es dafür eine offizielle Bibliothek, den semantischen Versionierer für npm .
Dan Dascalescu
1
Fand ein einfaches Skript , das Semvers vergleicht
vsync

Antworten:

132

Die Grundidee für diesen Vergleich wäre die Verwendung Array.split , Arrays von Teilen aus den Eingabezeichenfolgen abzurufen und dann Teilepaare aus den beiden Arrays zu vergleichen. Wenn die Teile nicht gleich sind, wissen wir, welche Version kleiner ist.

Es sind einige wichtige Details zu beachten:

  1. Wie sollen die Teile in jedem Paar verglichen werden? Die Frage möchte numerisch verglichen werden, aber was ist, wenn wir Versionszeichenfolgen haben, die nicht nur aus Ziffern bestehen (z. B. "1.0a")?
  2. Was soll passieren, wenn eine Versionszeichenfolge mehr Teile als die andere enthält? Höchstwahrscheinlich sollte "1.0" als weniger als "1.0.1" betrachtet werden, aber was ist mit "1.0.0"?

Hier ist der Code für eine Implementierung, die Sie direkt verwenden können ( Inhalt der Dokumentation ):

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

Diese Version vergleicht Teile auf natürliche Weise , akzeptiert keine Zeichensuffixe und betrachtet "1.7" als kleiner als "1.7.0". Der Vergleichsmodus kann in lexikografisch geändert werden, und kürzere Versionszeichenfolgen können mithilfe des optionalen dritten Arguments automatisch mit Nullen aufgefüllt werden.

Es gibt eine JSFiddle dass runs „Unit - Tests“ hier ; Es ist eine leicht erweiterte Version der Arbeit von ripper234 (danke).

Wichtiger Hinweis: Dieser Code verwendet Array.mapund Array.every, was bedeutet, dass er nicht in IE-Versionen vor 9 ausgeführt wird. Wenn Sie diese unterstützen müssen, müssen Sie Polyfills für die fehlenden Methoden bereitstellen.

Jon
quelle
16
Hier ist eine verbesserte Version mit einigen Unit-Tests: jsfiddle.net/ripper234/Xv9WL/28
ripper234
5
Hallo zusammen, ich habe dieses Wesentliche mit Tests und allem zu einem Gitrepo zusammengerollt und es auf npm und bower gestellt, damit ich es einfacher in meine Projekte aufnehmen kann. github.com/gabe0x02/version_compare
Gabriel Littman
2
@ GabrielLittman: Hey, danke, dass du dir die Zeit dafür genommen hast! Der gesamte Code auf SO ist jedoch standardmäßig mit CC-BY-SA lizenziert . Das bedeutet, dass Ihr Paket nicht GPL-lizenziert sein kann. Ich weiß, dass Anwälte nicht das sind, wofür jemand hier ist, aber es wäre gut, wenn Sie sie reparieren würden.
Jon
2
@GabrielLittman: GPL ist tatsächlich sehr restriktiv in dem Sinne, dass Sie gezwungen sind, den gesamten Code, der mit vorhandenem GPL-Code in Kontakt kommt, zu GPL-lizenzieren. Wie auch immer, als zukünftige Referenz: Eine gute und weit verbreitete Lizenz "Mach was du willst, ohne Bedingungen" ist MIT .
Jon
3
@GabrielLittman: Es gibt bereits etablierte Bibliotheken, die von erfahrenen Entwicklern geschrieben wurden und Semver-Vergleiche durchführen.
Dan Dascalescu
82

semver

Der von npm verwendete Parser für semantische Versionen.

$ npm semver installieren

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, '*')

Link zur semantischen Versionierung :
https://www.npmjs.com/package/semver#prerelease-identifiers

Mohammed Akdim
quelle
8
Ja. Dies ist die richtige Antwort - das Vergleichen von Versionen ist nicht trivial (siehe Nr. 11 auf semver.org ), und es gibt Bibliotheken auf Produktionsebene, die diese Aufgabe übernehmen.
Dan Dascalescu
7
Technisch gesehen sind es nicht die richtigen Antworten, da node.js und Javascript unterschiedlich sind. Ich nahm an, dass die ursprüngliche Frage eher für den Browser gedacht war. Aber Google hat mich hierher gebracht und zum Glück benutze ich Node :)
Lee Gary
2
NodeJS ist nicht nur eine serverseitige Lösung. Das Electron Framework bettet einen NodeJS für Desktop-Anwendungen ein. Dies ist eigentlich die Antwort, nach der ich gesucht habe.
Anthony Raymond
2
semver es ist ein npm Paket, es kann in jeder JS-Umgebung verwendet werden!
Dies ist
4
@artuska gut dann gehen Sie einfach für ein anderes Paket wie Semver-Compare - 233B (weniger als 0,5kB!) gzipped :)
Kano
50
// Return 1 if a > b
// Return -1 if a < b
// Return 0 if a == b
function compare(a, b) {
    if (a === b) {
       return 0;
    }

    var a_components = a.split(".");
    var b_components = b.split(".");

    var len = Math.min(a_components.length, b_components.length);

    // loop while the components are equal
    for (var i = 0; i < len; i++) {
        // A bigger than B
        if (parseInt(a_components[i]) > parseInt(b_components[i])) {
            return 1;
        }

        // B bigger than A
        if (parseInt(a_components[i]) < parseInt(b_components[i])) {
            return -1;
        }
    }

    // If one's a prefix of the other, the longer one is greater.
    if (a_components.length > b_components.length) {
        return 1;
    }

    if (a_components.length < b_components.length) {
        return -1;
    }

    // Otherwise they are the same.
    return 0;
}

console.log(compare("1", "2"));
console.log(compare("2", "1"));

console.log(compare("1.0", "1.0"));
console.log(compare("2.0", "1.0"));
console.log(compare("1.0", "2.0"));
console.log(compare("1.0.1", "1.0"));
Joe
quelle
Ich denke, die Zeile: var len = Math.min(a_components.length, b_components.length);Wird dazu führen, dass die Versionen 2.0.1.1 und 2.0.1 als gleich behandelt werden, oder?
Jon Egerton
1
Schauen Sie gleich nach der Schleife! Wenn eine Zeichenfolge ein Präfix der anderen ist (dh die Schleife erreicht das Ende), wird die längere als höher angesehen.
Joe
Vielleicht wurden Sie von meinem Stolpern über die englische Sprache in dem Kommentar abgeschreckt ...
Joe
@ Joe Ich weiß, ist eine etwas alte Antwort, aber ich habe die Funktion verwendet. Testen a = '7'und b = '7.0'zurückgeben, -1da 7.0 länger ist. Hast du einen Vorschlag dafür? ( console.log(compare("7", "7.0")); //returns -1)
RaphaelDDL
Ich nehme an, das fällt unter die Überschrift undefiniertes Verhalten. Wenn Sie diese Versionsnummern haben, können Sie die Logik sicher an Ihre Anforderungen anpassen.
Joe
48

Diese sehr kleine und dennoch sehr schnelle Vergleichsfunktion verwendet Versionsnummern beliebiger Länge und beliebiger Nummerngröße pro Segment .

Rückgabewerte:
- eine Zahl, < 0wenn a <b
- eine Zahl, > 0wenn a> b
- 0wenn a = b

Sie können es also als Vergleichsfunktion für Array.sort () verwenden.

BEARBEITEN : Bugfixed Version entfernt nachgestellte Nullen, um "1" und "1.0.0" als gleich zu erkennen

function cmpVersions (a, b) {
    var i, diff;
    var regExStrip0 = /(\.0+)+$/;
    var segmentsA = a.replace(regExStrip0, '').split('.');
    var segmentsB = b.replace(regExStrip0, '').split('.');
    var l = Math.min(segmentsA.length, segmentsB.length);

    for (i = 0; i < l; i++) {
        diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
        if (diff) {
            return diff;
        }
    }
    return segmentsA.length - segmentsB.length;
}

// TEST
console.log(
['2.5.10.4159',
 '1.0.0',
 '0.5',
 '0.4.1',
 '1',
 '1.1',
 '0.0.0',
 '2.5.0',
 '2',
 '0.0',
 '2.5.10',
 '10.5',
 '1.25.4',
 '1.2.15'].sort(cmpVersions));
// Result:
// ["0.0.0", "0.0", "0.4.1", "0.5", "1.0.0", "1", "1.1", "1.2.15", "1.25.4", "2", "2.5.0", "2.5.10", "2.5.10.4159", "10.5"]

LeJared
quelle
Fehlgeschlagen mit '0.0' und '0.0.0'. Siehe Geige: jsfiddle.net/emragins/9e9pweqg
Emragins
1
@emragins Wann müssten Sie das tun?
Skylar Ittner
1
@emragins: Ich sehe nicht, wo es fehlschlägt. Es gibt dort aus, ["0.0.0", "0.0", "0.4.1", "0.5", "1.0.0", "1", "1.1", "1.2.15", "1.25.4", "2", "2.5.0", "2.5.10", "2.5.10.4159", "10.5"] wo Ihr Code ausgegeben wird ["0.0", "0.0.0", "0.4.1", "0.5", "1", "1.0.0", "1.1", "1.2.15", "1.25.4", "2", "2.5.0", "2.5.10", "2.5.10.4159", "10.5"] , was vollkommen gleich ist, da 0.0 und 0.0.0 als gleich angesehen werden. Dies bedeutet, dass es unerheblich ist, ob '0.0' vor '0.0.0' liegt oder umgekehrt.
LeJared
Ich bin damit einverstanden, dass dies ein üblicher Punkt ist. Ich verwende dies mit github.com/jonmiles/bootstrap-treeview , das Knoten auf ähnliche Weise wie Versionen verknüpft , nur dass es sich wirklich nur um übergeordnete / untergeordnete Knoten und deren Indizes handelt. Ex. Eltern: 0.0, Kind: 0.0.0, 0.0.1. In dieser Ausgabe finden Sie weitere Informationen dazu, warum es mich interessiert: github.com/jonmiles/bootstrap-treeview/issues/251
emragins
1
Siehe Antwort hier stackoverflow.com/questions/6611824/why-do-we-need-to-use-radix . Ältere Browser erraten den Radix-Parameter, wenn nichts angegeben ist. Eine führende Null in einer Zahlenfolge wie der mittlere Teil in "1.09.12" wurde früher mit radix = 8 analysiert, was zu der Zahl 0 anstelle der erwarteten Zahl 9 führte.
LeJared
14

Entnommen aus http://java.com/js/deployJava.js :

    // return true if 'installed' (considered as a JRE version string) is
    // greater than or equal to 'required' (again, a JRE version string).
    compareVersions: function (installed, required) {

        var a = installed.split('.');
        var b = required.split('.');

        for (var i = 0; i < a.length; ++i) {
            a[i] = Number(a[i]);
        }
        for (var i = 0; i < b.length; ++i) {
            b[i] = Number(b[i]);
        }
        if (a.length == 2) {
            a[2] = 0;
        }

        if (a[0] > b[0]) return true;
        if (a[0] < b[0]) return false;

        if (a[1] > b[1]) return true;
        if (a[1] < b[1]) return false;

        if (a[2] > b[2]) return true;
        if (a[2] < b[2]) return false;

        return true;
    }
user123444555621
quelle
Einfach, aber auf drei Versionsfelder beschränkt.
Dan Dascalescu
11

Ich konnte hier keine Funktion finden, die das tut, was ich wollte. Also habe ich meine eigenen geschrieben. Das ist mein Beitrag. Ich hoffe, jemand findet es nützlich.

Vorteile:

  • Verarbeitet Versionszeichenfolgen beliebiger Länge. '1' oder '1.1.1.1.1'.

  • Der Standardwert ist 0, wenn nichts angegeben ist. Nur weil eine Zeichenfolge länger ist, heißt das nicht, dass es sich um eine größere Version handelt. ('1' sollte mit '1.0' und '1.0.0.0' identisch sein.)

  • Vergleichen Sie Zahlen, keine Zeichenfolgen. ('3' <'21' sollte wahr sein. Nicht falsch.)

  • Verschwenden Sie keine Zeit mit nutzlosen Vergleichen in der Schleife. (Vergleichen für ==)

  • Sie können Ihren eigenen Komparator auswählen.

Nachteile:

  • Es werden keine Buchstaben in der Versionszeichenfolge verarbeitet. (Ich weiß nicht, wie das überhaupt funktionieren würde?)

Mein Code, ähnlich der akzeptierten Antwort von Jon :

function compareVersions(v1, comparator, v2) {
    "use strict";
    var comparator = comparator == '=' ? '==' : comparator;
    if(['==','===','<','<=','>','>=','!=','!=='].indexOf(comparator) == -1) {
        throw new Error('Invalid comparator. ' + comparator);
    }
    var v1parts = v1.split('.'), v2parts = v2.split('.');
    var maxLen = Math.max(v1parts.length, v2parts.length);
    var part1, part2;
    var cmp = 0;
    for(var i = 0; i < maxLen && !cmp; i++) {
        part1 = parseInt(v1parts[i], 10) || 0;
        part2 = parseInt(v2parts[i], 10) || 0;
        if(part1 < part2)
            cmp = 1;
        if(part1 > part2)
            cmp = -1;
    }
    return eval('0' + comparator + cmp);
}

Beispiele :

compareVersions('1.2.0', '==', '1.2'); // true
compareVersions('00001', '==', '1.0.0'); // true
compareVersions('1.2.0', '<=', '1.2'); // true
compareVersions('2.2.0', '<=', '1.2'); // false
Viktor
quelle
Diese Version ist meiner Meinung nach besser als die in der genehmigten Antwort!
user3807877
1
Diese Funktion ist anfällig für Code-Injection, wenn der Komparatorparameter mit ungeprüfter Benutzereingabe verwendet wird! Beispiel: compareVersions ('1.2', '== 0; alert ("cotcha");', '1.2');
LeJared
@LeJared True. Als ich es schrieb, wollten wir es jedoch nicht mit vom Benutzer eingereichtem Code verwenden. Hätte es wahrscheinlich als Betrug ansprechen sollen. Ich habe jetzt den Code aktualisiert, um diese Möglichkeit auszuschließen. Jetzt, wenn Webpack und andere Bundler von node.js weit verbreitet sind, würde ich vorschlagen, dass die obige Antwort von Mohammed Akdim mit semver fast immer die richtige Antwort auf diese Frage ist.
Viktor
10

Einfache und kurze Funktion:

function isNewerVersion (oldVer, newVer) {
  const oldParts = oldVer.split('.')
  const newParts = newVer.split('.')
  for (var i = 0; i < newParts.length; i++) {
    const a = parseInt(newParts[i]) || 0
    const b = parseInt(oldParts[i]) || 0
    if (a > b) return true
    if (a < b) return false
  }
  return false
}

Tests:

isNewerVersion('1.0', '2.0') // true
isNewerVersion('1.0', '1.0.1') // true
isNewerVersion('1.0.1', '1.0.10') // true
isNewerVersion('1.0.1', '1.0.1') // false
isNewerVersion('2.0', '1.0') // false
isNewerVersion('2', '1.0') // false
isNewerVersion('2.0.0.0.0.1', '2.1') // true
isNewerVersion('2.0.0.0.0.1', '2.0') // false
Arthur Araújo
quelle
Sie können es vereinfachen mit: const a = ~~ newParts [i]; Tatsächlich ist dies die effizienteste Methode, um eine Zeichenfolge in eine Ganzzahl umzuwandeln, die 0 zurückgibt, wenn die Variable undefiniert ist oder nicht numerische Zeichen enthält.
Vanowm
5

Verzeihen Sie mir, wenn diese Idee bereits in einem Link besucht wurde, den ich nicht gesehen habe.

Ich hatte einige Erfolge bei der Umwandlung der Teile in eine gewichtete Summe wie folgt:

partSum = this.major * Math.Pow(10,9);
partSum += this.minor * Math.Pow(10, 6);
partSum += this.revision * Math.Pow(10, 3);
partSum += this.build * Math.Pow(10, 0);

Das machte Vergleiche sehr einfach (Vergleich eines Doppelpacks). Unsere Versionsfelder sind nie mehr als 4 Stellen.

7.10.2.184  -> 7010002184.0
7.11.0.1385 -> 7011001385.0

Ich hoffe, das hilft jemandem, da die vielen Bedingungen etwas übertrieben wirken.

Noxin
quelle
2
Dies wird brechen, wenn this.minor> 999 (wird sich mit Major überschneiden)
Afanasii Kurakin
5

Hier ist eine weitere Kurzversion, die mit einer beliebigen Anzahl von Unterversionen, gepolsterten Nullen und geraden Zahlen mit Buchstaben (1.0.0b3) funktioniert.

function compareVer(a, b)
{
    //treat non-numerical characters as lower version
    //replacing them with a negative number based on charcode of each character
    function fix(s)
    {
        return "." + (s.toLowerCase().charCodeAt(0) - 2147483647) + ".";
    }
    a = ("" + a).replace(/[^0-9\.]/g, fix).split('.');
    b = ("" + b).replace(/[^0-9\.]/g, fix).split('.');
    var c = Math.max(a.length, b.length);
    for (var i = 0; i < c; i++)
    {
        //convert to integer the most efficient way
        a[i] = ~~a[i];
        b[i] = ~~b[i];
        if (a[i] > b[i])
            return 1;
        else if (a[i] < b[i])
            return -1;
    }
    return 0;
}

Ausgabe:

0 : a = b

1 : a> b

-1 : a <b

1.0.0.0.0.0 = 1.0
1.0         < 1.0.1
1.0b1       < 1.0
1.0a        < 1.0b
1.1         > 1.0.1b
1.1alpha    < 1.1beta
1.1rc1      > 1.1beta
1.0001      > 1.00000.1.0.0.0.01

https://jsfiddle.net/vanowm/p7uvtbor/

vanowm
quelle
5

Antwort 2017:

v1 = '20.0.12'; 
v2 = '3.123.12';

compareVersions(v1,v2) 
// return positive: v1 > v2, zero:v1 == v2, negative: v1 < v2 
function compareVersions(v1, v2) {
        v1= v1.split('.')
        v2= v2.split('.')
        var len = Math.max(v1.length,v2.length)
        /*default is true*/
        for( let i=0; i < len; i++)
            v1 = Number(v1[i] || 0);
            v2 = Number(v2[i] || 0);
            if (v1 !== v2) return v1 - v2 ;
            i++;
        }
        return 0;
    }

Einfachster Code für moderne Browser:

 function compareVersion2(ver1, ver2) {
      ver1 = ver1.split('.').map( s => s.padStart(10) ).join('.');
      ver2 = ver2.split('.').map( s => s.padStart(10) ).join('.');
      return ver1 <= ver2;
 }

Die Idee hier ist, Zahlen zu vergleichen, aber in Form einer Zeichenfolge. Damit der Vergleich funktioniert, müssen die beiden Zeichenfolgen gleich lang sein. so:

"123" > "99" werden "123" > "099"
die Kurznummer „fix“ den Vergleich Klotzen

Hier fülle ich jeden Teil mit Nullen auf Längen von 10 auf und verwende dann einfach einen einfachen Zeichenfolgenvergleich für die Antwort

Beispiel:

var ver1 = '0.2.10', ver2=`0.10.2`
//become 
ver1 = '0000000000.0000000002.0000000010'
ver2 = '0000000000.0000000010.0000000002'
// then it easy to see that
ver1 <= ver2 // true
pery mimon
quelle
Würden Sie die Funktion erklären, compareVersion2was genau passiert?
Usman Wali
Gut, dann können Sie substringanstelle von padStartfür eine bessere Kompatibilität verwenden, dh var zeros = "0000000000"; '0.2.32'.split('.').map( s => zeros.substring(0, zeros.length-s.length) + s ).join('.') Sie erhalten 0000000000.0000000002.0000000032:)
Usman Wali
4

Meine weniger ausführliche Antwort als die meisten Antworten hier

/**
 * Compare two semver versions. Returns true if version A is greater than
 * version B
 * @param {string} versionA
 * @param {string} versionB
 * @returns {boolean}
 */
export const semverGreaterThan = function(versionA, versionB){
  var versionsA = versionA.split(/\./g),
    versionsB = versionB.split(/\./g)
  while (versionsA.length || versionsB.length) {
    var a = Number(versionsA.shift()), b = Number(versionsB.shift())
    if (a == b)
      continue
    return (a > b || isNaN(b))
  }
  return false
}
Verbündete
quelle
1
Sie sollten es zu einem Modul machen und es auf node.js platzieren. Bis dahin stehle ich Ihren Code mit Zuschreibung an Sie. Danke dafür.
r3wt
3

Obwohl diese Frage schon viel hat Antworten hat, wirbt jede für ihre eigene Hinterhoflösung, während wir dafür ein ganzes Ökosystem von (kampf-) getesteten Bibliotheken haben.

Eine schnelle Suche in NPM , GitHub , X gibt uns einige schöne Bibliotheken, und ich möchte einige durchgehen:

semver-compareist eine sehr leichte (~ 230B) Bibliothek, die besonders nützlich ist, wenn Sie nach Versionsnummern sortieren möchten, wenn die exponierte Methode der Bibliothek zurückgegeben wird -1, 0oder 1entsprechend.

Der Kern der Bibliothek:

module.exports = function cmp (a, b) {
    var pa = a.split('.');
    var pb = b.split('.');
    for (var i = 0; i < 3; i++) {
        var na = Number(pa[i]);
        var nb = Number(pb[i]);
        if (na > nb) return 1;
        if (nb > na) return -1;
        if (!isNaN(na) && isNaN(nb)) return 1;
        if (isNaN(na) && !isNaN(nb)) return -1;
    }
    return 0;
};

compare-semver ist ziemlich kräftig (~ 4,4 kB gezippt), ermöglicht aber einige nette, einzigartige Vergleiche, wie zum Beispiel das Min / Max eines Stapel von Versionen zu finden oder herauszufinden, ob die bereitgestellte Version einzigartig ist oder weniger als alles andere in einer Sammlung von Versionen.

compare-versionsist eine weitere kleine Bibliothek (~ 630B gzipped) und folgt der Spezifikation gut, was bedeutet, dass Sie Versionen mit Alpha / Beta-Flags und sogar Platzhaltern vergleichen können (wie bei Minor / Patch-Versionen: 1.0.xoder1.0.* )

Der Punkt ist: Es ist nicht immer erforderlich, Code aus StackOverflow zu kopieren und einzufügen, wenn Sie über den Paketmanager Ihrer Wahl anständige (Unit-) getestete Versionen finden.

kano
quelle
3

Ich stand vor einem ähnlichen Problem und hatte bereits eine Lösung dafür gefunden. Probieren Sie es einfach aus.

Es gibt 0für equal, 1wenn die Version ist , greaterund -1wenn es sich umless

function compareVersion(currentVersion, minVersion) {
  let current = currentVersion.replace(/\./g," .").split(' ').map(x=>parseFloat(x,10))
  let min = minVersion.replace(/\./g," .").split(' ').map(x=>parseFloat(x,10))

  for(let i = 0; i < Math.max(current.length, min.length); i++) {
    if((current[i] || 0) < (min[i] || 0)) {
      return -1
    } else if ((current[i] || 0) > (min[i] || 0)) {
      return 1
    }
  }
  return 0
}


console.log(compareVersion("81.0.1212.121","80.4.1121.121"));
console.log(compareVersion("81.0.1212.121","80.4.9921.121"));
console.log(compareVersion("80.0.1212.121","80.4.9921.121"));
console.log(compareVersion("4.4.0","4.4.1"));
console.log(compareVersion("5.24","5.2"));
console.log(compareVersion("4.1","4.1.2"));
console.log(compareVersion("4.1.2","4.1"));
console.log(compareVersion("4.4.4.4","4.4.4.4.4"));
console.log(compareVersion("4.4.4.4.4.4","4.4.4.4.4"));
console.log(compareVersion("0","1"));
console.log(compareVersion("1","1"));
console.log(compareVersion("1","1.0.00000.0000"));
console.log(compareVersion("","1"));
console.log(compareVersion("10.0.1","10.1"));

Super Dev
quelle
2

Die Idee ist, zwei Versionen zu vergleichen und zu wissen, welche die größte ist. Wir löschen "." und wir vergleichen jede Position des Vektors mit der anderen.

// Return 1  if a > b
// Return -1 if a < b
// Return 0  if a == b

function compareVersions(a_components, b_components) {

   if (a_components === b_components) {
       return 0;
   }

   var partsNumberA = a_components.split(".");
   var partsNumberB = b_components.split(".");

   for (var i = 0; i < partsNumberA.length; i++) {

      var valueA = parseInt(partsNumberA[i]);
      var valueB = parseInt(partsNumberB[i]);

      // A bigger than B
      if (valueA > valueB || isNaN(valueB)) {
         return 1;
      }

      // B bigger than A
      if (valueA < valueB) {
         return -1;
      }
   }
}
Marc
quelle
Epische Antwort, genau das, wonach ich gesucht habe.
Vince
2
// Returns true if v1 is bigger than v2, and false if otherwise.
function isNewerThan(v1, v2) {
      v1=v1.split('.');
      v2=v2.split('.');
      for(var i = 0; i<Math.max(v1.length,v2.length); i++){
        if(v1[i] == undefined) return false; // If there is no digit, v2 is automatically bigger
        if(v2[i] == undefined) return true; // if there is no digit, v1 is automatically bigger
        if(v1[i] > v2[i]) return true;
        if(v1[i] < v2[i]) return false;
      }
      return false; // Returns false if they are equal
    }
Dyllan M.
quelle
1
Willkommen bei SO. Diese Frage hat bereits viele gute Antworten. Bitte fügen Sie keine neuen Antworten hinzu, es sei denn, Sie fügen etwas Neues hinzu.
ext
1

Die replace()Funktion ersetzt nur das erste Vorkommen in der Zeichenfolge. Ersetzen wir also das .durch ,. Löschen Sie anschließend alle .und machen Sie das ,zu .erneut und analysieren Sie es, um zu schweben.

for(i=0; i<versions.length; i++) {
    v = versions[i].replace('.', ',');
    v = v.replace(/\./g, '');
    versions[i] = parseFloat(v.replace(',', '.'));
}

Zum Schluss sortieren Sie es:

versions.sort();
Sascha Galeere
quelle
1

Schauen Sie sich diesen Blog-Beitrag an . Diese Funktion funktioniert für numerische Versionsnummern.

function compVersions(strV1, strV2) {
  var nRes = 0
    , parts1 = strV1.split('.')
    , parts2 = strV2.split('.')
    , nLen = Math.max(parts1.length, parts2.length);

  for (var i = 0; i < nLen; i++) {
    var nP1 = (i < parts1.length) ? parseInt(parts1[i], 10) : 0
      , nP2 = (i < parts2.length) ? parseInt(parts2[i], 10) : 0;

    if (isNaN(nP1)) { nP1 = 0; }
    if (isNaN(nP2)) { nP2 = 0; }

    if (nP1 != nP2) {
      nRes = (nP1 > nP2) ? 1 : -1;
      break;
    }
  }

  return nRes;
};

compVersions('10', '10.0'); // 0
compVersions('10.1', '10.01.0'); // 0
compVersions('10.0.1', '10.0'); // 1
compVersions('10.0.1', '10.1'); // -1
David
quelle
1

Wenn wir beispielsweise überprüfen möchten, ob die aktuelle jQuery-Version kleiner als 1,8 ist, parseFloat($.ui.version) < 1.8 )würde dies ein falsches Ergebnis liefern, wenn die Version "1.10.1" ist, da parseFloat ("1.10.1") zurückgegeben wird 1.1. Ein String-Vergleich würde auch schief gehen, da "1.8" < "1.10"ausgewertet wirdfalse .

Wir brauchen also einen solchen Test

if(versionCompare($.ui.version, "1.8") < 0){
    alert("please update jQuery");
}

Die folgende Funktion behandelt dies korrekt:

/** Compare two dotted version strings (like '10.2.3').
 * @returns {Integer} 0: v1 == v2, -1: v1 < v2, 1: v1 > v2
 */
function versionCompare(v1, v2) {
    var v1parts = ("" + v1).split("."),
        v2parts = ("" + v2).split("."),
        minLength = Math.min(v1parts.length, v2parts.length),
        p1, p2, i;
    // Compare tuple pair-by-pair. 
    for(i = 0; i < minLength; i++) {
        // Convert to integer if possible, because "8" > "10".
        p1 = parseInt(v1parts[i], 10);
        p2 = parseInt(v2parts[i], 10);
        if (isNaN(p1)){ p1 = v1parts[i]; } 
        if (isNaN(p2)){ p2 = v2parts[i]; } 
        if (p1 == p2) {
            continue;
        }else if (p1 > p2) {
            return 1;
        }else if (p1 < p2) {
            return -1;
        }
        // one operand is NaN
        return NaN;
    }
    // The longer tuple is always considered 'greater'
    if (v1parts.length === v2parts.length) {
        return 0;
    }
    return (v1parts.length < v2parts.length) ? -1 : 1;
}

Hier sind einige Beispiele:

// compare dotted version strings
console.assert(versionCompare("1.8",      "1.8.1")    <   0);
console.assert(versionCompare("1.8.3",    "1.8.1")    >   0);
console.assert(versionCompare("1.8",      "1.10")     <   0);
console.assert(versionCompare("1.10.1",   "1.10.1")   === 0);
// Longer is considered 'greater'
console.assert(versionCompare("1.10.1.0", "1.10.1")   >   0);
console.assert(versionCompare("1.10.1",   "1.10.1.0") <   0);
// Strings pairs are accepted
console.assert(versionCompare("1.x",      "1.x")      === 0);
// Mixed int/string pairs return NaN
console.assert(isNaN(versionCompare("1.8", "1.x")));
//works with plain numbers
console.assert(versionCompare("4", 3)   >   0);

Hier finden Sie eine Live-Beispiel- und Testsuite: http://jsfiddle.net/mar10/8KjvP/

mar10
quelle
arghh, habe gerade bemerkt, dass ripper234 vor ein paar Monaten eine Geigen-URL in eof der Kommentare gepostet hat, die ziemlich ähnlich ist. Wie auch immer, ich behalte meine Antwort hier ...
10. März
Dieser wird auch (wie die meisten Varianten) in diesen Fällen fehlschlagen: versionCompare ('1.09', '1.1') gibt "1" zurück, genauso wie versionCompare ('1.702', '1.8').
shaman.sir
Der Code wertet "1.09"> "1.1" und "1.702"> "1.8" aus, was ich für richtig halte. Wenn Sie nicht einverstanden sind: Können Sie auf eine Ressource verweisen, die Ihre Meinung stützt?
10. März
Es hängt von Ihren Prinzipien ab - wie ich weiß, gibt es keine strengen Regeln oder so. In Bezug auf Ressourcen heißt es in einem Wikipedia-Artikel für "Software-Versionierung" in "Inkrementieren von Sequenzen", dass 1.81 eine Nebenversion von 1.8 sein kann, daher sollte 1.8 als 1.80 lauten. Der semantische Versionierungsartikel semver.org/spec/v2.0.0.html besagt auch, dass 1.9.0 -> 1.10.0 -> 1.11.0, so dass 1.9.0 im Vergleich so wie 1.90.0 behandelt wird. Nach dieser Logik war Version 1.702 vor Version 1.8, die als 1.800 behandelt wird.
shaman.sir
1
Ich sehe, dass einige Regeln 1,8 <1,81 <1,9 behandeln. Aber im Semver würden Sie 1.8.1 anstelle von 1.81 verwenden. Semver (so wie ich es verstehe) basiert auf der Annahme, dass das Inkrementieren eines Teils immer eine "spätere" Version erzeugt, also 1,8 <1,8,1 <1,9 <1,10 <1,81 <1,90 <1,100. Ich sehe keinen Hinweis darauf, dass dies ebenfalls auf zwei Ziffern beschränkt ist. Daher würde ich sagen, dass mein Code vollständig mit Semver kompatibel ist.
10. März
1

Hier ist eine Coffeescript-Implementierung, die für die Verwendung mit Array.sort geeignet ist und von anderen Antworten hier inspiriert wurde:

# Returns > 0 if v1 > v2 and < 0 if v1 < v2 and 0 if v1 == v2
compareVersions = (v1, v2) ->
  v1Parts = v1.split('.')
  v2Parts = v2.split('.')
  minLength = Math.min(v1Parts.length, v2Parts.length)
  if minLength > 0
    for idx in [0..minLength - 1]
      diff = Number(v1Parts[idx]) - Number(v2Parts[idx])
      return diff unless diff is 0
  return v1Parts.length - v2Parts.length
LOAS
quelle
Dies ist inspiriert von LeJareds Antwort .
Dan Dascalescu
Dies funktioniert nicht richtig. Hier ist das Ergebnis. Ergebnis ['1.1.1', '2.1.1', '3.3.1.0', '3.1.1.0']
ertan2002
1

Ich habe ein Knotenmodul zum Sortieren von Versionen geschrieben. Sie finden es hier: version-sort

Eigenschaften :

  • Keine Begrenzung der Sequenzen '1.0.1.5.53.54654.114.1.154.45' funktioniert
  • Keine Begrenzung der Sequenzlänge: '1.1546515465451654654654654138754431574364321353734' funktioniert
  • kann Objekte nach Version sortieren (siehe README)
  • Stufen (wie Alpha, Beta, RC1, RC2)

Zögern Sie nicht, ein Problem zu öffnen, wenn Sie eine andere Funktion benötigen.

Quentin Rossetti
quelle
1

Dies funktioniert für numerische Versionen beliebiger Länge, die durch einen Punkt getrennt sind. Es wird nur dann true zurückgegeben, wenn myVersion> = minimumVersion ist, wobei davon ausgegangen wird, dass Version 1 kleiner als 1.0, Version 1.1 kleiner als 1.1.0 usw. ist. Es sollte ziemlich einfach sein, zusätzliche Bedingungen hinzuzufügen, z. B. Zahlen zu akzeptieren (einfach in eine Zeichenfolge konvertieren) und hexadezimal zu setzen oder das Trennzeichen dynamisch zu machen (einfach einen Trennzeichenparameter hinzufügen und dann das "." Durch den Parameter ersetzen).

function versionCompare(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 true;
        }
        if(Number(v1[i]) < Number(v2[i])) {
            return false;
        }           
    }

    return (v1.length >= v2.length);
}

Hier sind einige Tests:

console.log(versionCompare("4.4.0","4.4.1"));
console.log(versionCompare("5.24","5.2"));
console.log(versionCompare("4.1","4.1.2"));
console.log(versionCompare("4.1.2","4.1"));
console.log(versionCompare("4.4.4.4","4.4.4.4.4"));
console.log(versionCompare("4.4.4.4.4.4","4.4.4.4.4"));
console.log(versionCompare("0","1"));
console.log(versionCompare("1","1"));
console.log(versionCompare("","1"));
console.log(versionCompare("10.0.1","10.1"));

Alternativ ist hier eine rekursive Version

function versionCompare(myVersion, minimumVersion) {
  return recursiveCompare(myVersion.split("."),minimumVersion.split("."),Math.min(myVersion.length, minimumVersion.length),0);
}

function recursiveCompare(v1, v2,minLength, index) {
  if(Number(v1[index]) < Number(v2[index])) {
    return false;
  }
  if(Number(v1[i]) < Number(v2[i])) {
    return true;
    }
  if(index === minLength) {
    return (v1.length >= v2.length);
  }
  return recursiveCompare(v1,v2,minLength,index+1);
}
Will Schulz
quelle
1

Ich finde einen einfachsten Weg, sie zu vergleichen. Ich bin mir nicht sicher, ob es das ist, was Sie wollen. Wenn ich den folgenden Code in der Konsole ausführe, ist dies sinnvoll, und wenn ich die sort () -Methode verwende, kann ich das sortierte Array der Versionszeichenfolge abrufen. Es basiert auf der alphabetischen Reihenfolge.

"1.0" < "1.0.1" //true
var arr = ["1.0.1", "1.0", "3.2.0", "1.3"]
arr.sort();     //["1.0", "1.0.1", "1.3", "3.2.0"]
inoutwhy
quelle
3
Es funktioniert nicht gut für zweistellige Versionsnummern, z. B. 1.10.0.
Leukipp
1

Sie könnten String#localeComparemit verwendenoptions

Empfindlichkeit

Welche Unterschiede in den Zeichenfolgen sollten zu Ergebniswerten ungleich Null führen? Mögliche Werte sind:

  • "base": Nur Zeichenfolgen, die sich in den Basisbuchstaben unterscheiden, werden als ungleich verglichen. Beispiele: a ≠ b, a = á, a = A.
  • "accent": Nur Zeichenfolgen, die sich in Basisbuchstaben oder Akzenten und anderen diakritischen Zeichen unterscheiden, werden als ungleich verglichen. Beispiele: a ≠ b, a ≠ á,a = A .
  • "case": Nur Zeichenfolgen, die sich in Basisbuchstaben oder Groß- / Kleinschreibung unterscheiden, werden als ungleich verglichen. Beispiele: a ≠ b, a = á,a ≠ A .
  • "variant": Zeichenfolgen, die sich in Basisbuchstaben, Akzenten und anderen diakritischen Zeichen oder Groß- und Kleinschreibung unterscheiden, werden als ungleich verglichen. Andere Unterschiede können ebenfalls berücksichtigt werden. Beispiele: a ≠ b, a ≠ á, a ≠ A.

Der Standardwert ist "Variante" für die Verwendung "Sortieren". Das Gebietsschema hängt von der Verwendung "Suche" ab.

numerisch

Gibt an, ob eine numerische Sortierung verwendet werden soll, sodass "1" <"2" <"10". Mögliche Werte sind trueund false; Der Standardwert ist false. Diese Option kann über eine options-Eigenschaft oder über einen Unicode-Erweiterungsschlüssel festgelegt werden. Wenn beide angegeben sind, hat die optionsEigenschaft Vorrang. Implementierungen sind nicht erforderlich, um diese Eigenschaft zu unterstützen.

var versions = ["2.0.1", "2.0", "1.0", "1.0.1", "2.0.0.1"];

versions.sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }));

console.log(versions);

Nina Scholz
quelle
Wie funktioniert das eigentlich? Was ist das undefinedObige, Sprache? Wie kommt es, dass du es
schaffst
undefinedist der Gebietsschema-Teil, wird hier nicht verwendet.
Nina Scholz
0

Könntest du sie nicht in Zahlen umwandeln und dann nach Größe sortieren? Fügen Sie Nullen an diejenigen an Zahlen mit einer Länge von <4 an

in der Konsole herumgespielt:

$(["1.0.0.0", "1.0.1.0", "2.0.0.0", "2.0.0.1", "2.0.1", "3.0"]).each(function(i,e) {
    var n =   e.replace(/\./g,"");
    while(n.length < 4) n+="0" ; 
    num.push(  +n  )
});

Je größer die Version, desto größer die Anzahl. Bearbeiten: muss wahrscheinlich angepasst werden, um größere Versionsserien zu berücksichtigen

Contra
quelle
Das war nur ein Beispiel, da er einige Dinge selbst erledigen muss: P Anstelle von 4 erhalten Sie die Anzahl der Zahlen, die die größte Version hat, und füllen Sie dann die niedrigeren mit Nullen
Contra
0

Das ist ein ordentlicher Trick. Wenn Sie mit numerischen Werten zwischen einem bestimmten Wertebereich arbeiten, können Sie jeder Ebene des Versionsobjekts einen Wert zuweisen. Zum Beispiel wird "größter Wert" hier auf 0xFF gesetzt, was Ihrer Versionierung einen sehr "IP" -Look verleiht.

Dies behandelt auch die alphanumerische Versionierung (dh 1.2a <1.2b)

// The version compare function
function compareVersion(data0, data1, levels) {
    function getVersionHash(version) {
        var value = 0;
        version = version.split(".").map(function (a) {
            var n = parseInt(a);
            var letter = a.replace(n, "");
            if (letter) {
                return n + letter[0].charCodeAt() / 0xFF;
            } else {
                return n;
            }
        });
        for (var i = 0; i < version.length; ++i) {
            if (levels === i) break;
            value += version[i] / 0xFF * Math.pow(0xFF, levels - i + 1);
        }
        return value;
    };
    var v1 = getVersionHash(data0);
    var v2 = getVersionHash(data1);
    return v1 === v2 ? -1 : v1 > v2 ? 0 : 1;
};
// Returns 0 or 1, correlating to input A and input B
// Direct match returns -1
var version = compareVersion("1.254.253", "1.254.253a", 3);
Michael Deal
quelle
0

Ich mag die Version von @ mar10 , obwohl aus meiner Sicht die Möglichkeit eines Missbrauchs besteht (anscheinend ist dies nicht der Fall, wenn Versionen mit dem Semantic Versioning- Dokument kompatibel sind , kann aber der Fall sein, wenn eine "Build-Nummer" verwendet wird ):

versionCompare( '1.09', '1.1');  // returns 1, which is wrong:  1.09 < 1.1
versionCompare('1.702', '1.8');  // returns 1, which is wrong: 1.702 < 1.8

Das Problem hierbei ist, dass Teilnummern der Versionsnummer in einigen Fällen mit ausgeschnittenen nachgestellten Nullen geschrieben werden (zumindest wie ich es kürzlich bei Verwendung einer anderen Software sehe), was dem rationalen Teil einer Nummer ähnlich ist, also:

5.17.2054 > 5.17.2
5.17.2 == 5.17.20 == 5.17.200 == ... 
5.17.2054 > 5.17.20
5.17.2054 > 5.17.200
5.17.2054 > 5.17.2000
5.17.2054 > 5.17.20000
5.17.2054 < 5.17.20001
5.17.2054 < 5.17.3
5.17.2054 < 5.17.30

Die erste (oder sowohl die erste als auch die zweite) Versionsunternummer wird jedoch immer als ganzzahliger Wert behandelt, dem sie tatsächlich entspricht.

Wenn Sie diese Art der Versionierung verwenden, können Sie im Beispiel nur einige Zeilen ändern:

// replace this:
p1 = parseInt(v1parts[i], 10);
p2 = parseInt(v2parts[i], 10);
// with this:
p1 = i/* > 0 */ ? parseFloat('0.' + v1parts[i], 10) : parseInt(v1parts[i], 10);
p2 = i/* > 0 */ ? parseFloat('0.' + v2parts[i], 10) : parseInt(v2parts[i], 10);

Also jede Unternummer mit Ausnahme des ersten wird als Schwimmer verglichen werden, so 09und 1wird worden 0.09und 0.1dementsprechend und richtig auf diese Weise verglichen. 2054und 3wird 0.2054und werden0.3 .

Die vollständige Version lautet dann (Credits an @ mar10 ):

/** Compare two dotted version strings (like '10.2.3').
 * @returns {Integer} 0: v1 == v2, -1: v1 < v2, 1: v1 > v2
 */
function versionCompare(v1, v2) {
    var v1parts = ("" + v1).split("."),
        v2parts = ("" + v2).split("."),
        minLength = Math.min(v1parts.length, v2parts.length),
        p1, p2, i;
    // Compare tuple pair-by-pair. 
    for(i = 0; i < minLength; i++) {
        // Convert to integer if possible, because "8" > "10".
        p1 = i/* > 0 */ ? parseFloat('0.' + v1parts[i], 10) : parseInt(v1parts[i], 10);;
        p2 = i/* > 0 */ ? parseFloat('0.' + v2parts[i], 10) : parseInt(v2parts[i], 10);
        if (isNaN(p1)){ p1 = v1parts[i]; } 
        if (isNaN(p2)){ p2 = v2parts[i]; } 
        if (p1 == p2) {
            continue;
        }else if (p1 > p2) {
            return 1;
        }else if (p1 < p2) {
            return -1;
        }
        // one operand is NaN
        return NaN;
    }
    // The longer tuple is always considered 'greater'
    if (v1parts.length === v2parts.length) {
        return 0;
    }
    return (v1parts.length < v2parts.length) ? -1 : 1;
}

PS Es ist langsamer, aber es ist auch möglich, bei der Wiederverwendung derselben Vergleichsfunktion daran zu denken, dass die Zeichenfolge tatsächlich das Zeichenarray ist:

 function cmp_ver(arr1, arr2) {
     // fill the tail of the array with smaller length with zeroes, to make both array have the same length
     while (min_arr.length < max_arr.length) {
         min_arr[min_arr.lentgh] = '0';
     }
     // compare every element in arr1 with corresponding element from arr2, 
     // but pass them into the same function, so string '2054' will act as
     // ['2','0','5','4'] and string '19', in this case, will become ['1', '9', '0', '0']
     for (i: 0 -> max_length) {
         var res = cmp_ver(arr1[i], arr2[i]);
         if (res !== 0) return res;
     }
 }
shaman.sir
quelle
0

Ich habe dies basierend auf der Kons-Idee gemacht und es für die Java-Version "1.7.0_45" optimiert. Es ist nur eine Funktion, die eine Versionszeichenfolge in einen Float konvertieren soll. Dies ist die Funktion:

function parseVersionFloat(versionString) {
    var versionArray = ("" + versionString)
            .replace("_", ".")
            .replace(/[^0-9.]/g, "")
            .split("."),
        sum = 0;
    for (var i = 0; i < versionArray.length; ++i) {
        sum += Number(versionArray[i]) / Math.pow(10, i * 3);
    }
    console.log(versionString + " -> " + sum);
    return sum;
}

Die Zeichenfolge "1.7.0_45" wird in 1.0070000450000001 konvertiert und ist für einen normalen Vergleich ausreichend. Hier erklärter Fehler: Wie gehe ich mit der Genauigkeit von Gleitkommazahlen in JavaScript um? . Wenn Sie mehr als 3 Stellen benötigen, können Sie den Teiler ändernMath.pow(10, i * 3); .

Die Ausgabe sieht folgendermaßen aus:

1.7.0_45         > 1.007000045
ver 1.7.build_45 > 1.007000045
1.234.567.890    > 1.23456789
Adrian S.
quelle
0

Ich hatte das gleiche Problem beim Versionsvergleich, aber mit Versionen, die möglicherweise etwas enthielten (dh Trennzeichen, die keine Punkte waren, Erweiterungen wie rc1, rc2 ...).

Ich habe dies verwendet, wodurch die Versionszeichenfolgen im Grunde genommen in Zahlen und Nicht-Zahlen aufgeteilt wurden, und versucht, sie entsprechend dem Typ zu vergleichen.

function versionCompare(a,b) {
  av = a.match(/([0-9]+|[^0-9]+)/g)
  bv = b.match(/([0-9]+|[^0-9]+)/g)
  for (;;) {
    ia = av.shift();
    ib = bv.shift();
    if ( (typeof ia === 'undefined') && (typeof ib === 'undefined') ) { return 0; }
    if (typeof ia === 'undefined') { ia = '' }
    if (typeof ib === 'undefined') { ib = '' }

    ian = parseInt(ia);
    ibn = parseInt(ib);
    if ( isNaN(ian) || isNaN(ibn) ) {
      // non-numeric comparison
      if (ia < ib) { return -1;}
      if (ia > ib) { return 1;}
    } else {
      if (ian < ibn) { return -1;}
      if (ian > ibn) { return 1;}
    }
  }
}

Für einige Fälle gibt es hier einige Annahmen, zum Beispiel: "1.01" === "1.1" oder "1.8" <"1.71". "1.0.0-rc.1" <"1.0.0" kann nicht verwaltet werden, wie in Semantic versionning 2.0.0 angegeben

Uriel
quelle
0

Durch die Vorverarbeitung der Versionen vor dem Sortieren wird parseInt nicht unnötig mehrmals aufgerufen. Wenn ich eine Array # -Karte verwende, die dem Vorschlag von Michael Deal ähnelt, verwende ich folgende Sortierung, um die neueste Version eines dreiteiligen Standardsemvers zu finden:

var semvers = ["0.1.0", "1.0.0", "1.1.0", "1.0.5"];

var versions = semvers.map(function(semver) {
    return semver.split(".").map(function(part) {
        return parseInt(part);
    });
});

versions.sort(function(a, b) {
    if (a[0] < b[0]) return 1;
    else if (a[0] > b[0]) return -1;
    else if (a[1] < b[1]) return 1;
    else if (a[1] > b[1]) return -1;
    else if (a[2] < b[2]) return 1;
    else if (a[2] > b[2]) return -1;
    return 0;
});

var newest = versions[0].join(".");
console.log(newest); // "1.1.0"

theGecko
quelle