Js का उपयोग करके सॉफ्टवेयर संस्करण संख्या की तुलना कैसे करें? (केवल संख्या)


164

यहाँ सॉफ्टवेयर संस्करण संख्या है:

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

मैं इसकी तुलना कैसे कर सकता हूँ ?? मान लें कि सही क्रम है:

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

यह विचार सरल है ...: पहला अंक पढ़ें, की तुलना में, दूसरा, उसके बाद तीसरा .... लेकिन मैं संस्करण संख्या को फ्लोट नंबर में परिवर्तित नहीं कर सकता .... आप संस्करण संख्या भी देख सकते हैं जैसे यह:

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

और यह देखने के लिए अधिक स्पष्ट है कि पीछे क्या विचार है ... लेकिन, इसे कंप्यूटर प्रोग्राम में कैसे बदला जाए ?? क्या किसी को इस बारे में कोई विचार है कि इसे कैसे छाँटना है? धन्यवाद।


5
यह एक अच्छा fizzbuzz- प्रकार का साक्षात्कार प्रश्न होगा।
स्टीव क्लैरिज

2
यही कारण है कि सभी सॉफ्टवेयर संस्करण संख्या 2001403 की तरह पूर्णांक होनी चाहिए। जब ​​आप इसे कुछ अनुकूल तरीके से प्रदर्शित करना चाहते हैं जैसे "2.0.14.3" तो आप प्रस्तुति समय पर संस्करण संख्या को प्रारूपित करते हैं।
jarmod

2
यहां सामान्य समस्या सिमेंटिक वर्जन की तुलना है, और यह गैर-तुच्छ है (देखें # 11 semver.org पर )। सौभाग्य से, उस के लिए एक आधिकारिक पुस्तकालय है, npm के लिए अर्थ वर्कर
डैन डस्केल्सस्कु

1
एक साधारण स्क्रिप्ट मिली, जो वीवर्स की तुलना करती है
vsync

जवाबों:


133

यह तुलना करने का मूल विचार Array.splitइनपुट स्ट्रिंग्स से भागों के सरणियों को प्राप्त करने के लिए उपयोग करना होगा और फिर दो सरणियों से भागों के जोड़े की तुलना करना होगा; यदि भाग समान नहीं हैं, तो हम जानते हैं कि कौन सा संस्करण छोटा है।

ध्यान रखने के लिए कुछ महत्वपूर्ण विवरण हैं:

  1. प्रत्येक जोड़ी में भागों की तुलना कैसे की जानी चाहिए? सवाल संख्यात्मक रूप से तुलना करना चाहता है, लेकिन क्या होगा यदि हमारे पास संस्करण तार हैं जो सिर्फ अंकों से नहीं बने हैं (उदाहरण के लिए "1.03")?
  2. यदि एक संस्करण स्ट्रिंग में अन्य की तुलना में अधिक भाग हैं तो क्या होना चाहिए? सबसे अधिक संभावना है कि "1.0" को "1.0.1" से कम माना जाना चाहिए, लेकिन "1.0.0" के बारे में क्या?

यहां एक कार्यान्वयन के लिए कोड है जिसे आप सीधे उपयोग कर सकते हैं ( प्रलेखन के साथ जीआईएस ):

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

यह संस्करण स्वाभाविक रूप से भागों की तुलना करता है, चरित्र प्रत्ययों को स्वीकार नहीं करता है और "1.7" को "1.7.0" से छोटा मानता है। तुलना मोड को लेक्सियोग्राफिक में बदला जा सकता है और छोटे संस्करण के तार को वैकल्पिक रूप से वैकल्पिक तीसरे तर्क का उपयोग करके शून्य-गद्देदार किया जा सकता है।

एक JSField है जो यहां "यूनिट टेस्ट" चलाता है ; यह ripper234 के काम का थोड़ा विस्तारित संस्करण है (धन्यवाद)।

महत्वपूर्ण नोट: यह कोड उपयोग करता है Array.mapऔर Array.every, जिसका अर्थ है कि यह IE संस्करणों में 9 से पहले नहीं चलेगा। यदि आपको उन लोगों का समर्थन करने की आवश्यकता है, तो आपको लापता तरीकों के लिए पॉलीफिल प्रदान करना होगा।


16
यहाँ कुछ यूनिट परीक्षणों के साथ एक बेहतर संस्करण है: jsfiddle.net/ripper234/Xv9WL/28
ripper234

5
हे सब, मैं इस gistrepo में परीक्षण और सब कुछ के साथ लुढ़का हुआ है और इसे npm और bower पर रखा है ताकि मैं इसे और अधिक आसानी से अपनी परियोजनाओं में शामिल कर सकूं। github.com/gabe0x02/version_compare
गेब्रियल लिटमैन

2
@ गैब्रिएलिटमैन: अरे, ऐसा करने के लिए समय निकालने के लिए धन्यवाद! हालांकि SO पर सभी कोड डिफ़ॉल्ट रूप से CC-BY-SA के साथ लाइसेंस प्राप्त है । इसका मतलब है कि आपके पास आपका पैकेज GPL- लाइसेंस नहीं हो सकता है। मुझे पता है कि लॉयरिंग वह नहीं है जो किसी के लिए यहां है, लेकिन यह अच्छा होगा यदि आप इसे तय करते हैं।
जॉन

2
@GabrielLittman: GPL वास्तव में इस अर्थ में बहुत प्रतिबंधक है कि आप GPL-लाइसेंस के लिए मजबूर हैं जो मौजूदा GPL कोड के संपर्क में आता है। वैसे भी, भविष्य के संदर्भ के लिए: एक अच्छा और व्यापक रूप से उपयोग किया जाता है "जो भी आप चाहते हैं, कोई तार संलग्न नहीं है" लाइसेंस एमआईटी है
जॉन

3
@ गैब्रिएलिटमैन: अनुभवी देवों द्वारा लिखित पहले से स्थापित पुस्तकालय हैं जो सेवर की तुलना करते हैं।
डैन डस्केल्सस्कू

82

semver

शब्दार्थ संस्करण पार्सर npm द्वारा उपयोग किया जाता है।

$ npm सेमेस्टर स्थापित करें

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

सिमेंटिक संस्करण लिंक :
https://www.npmjs.com/package/semver#prerelease-identifiers


8
हाँ। यह सही उत्तर है - संस्करणों की तुलना गैर-तुच्छ है ( semver.org पर # 11 देखें ), और उत्पादन स्तर के पुस्तकालय हैं जो काम करते हैं।
डैन डस्केल्सस्कु

7
तकनीकी रूप से, यह सही उत्तर नहीं है, क्योंकि नोड.जेएस और जावास्क्रिप्ट अलग है। मुझे लगता है कि मूल प्रश्न ब्राउज़र के लिए अधिक लक्षित था। लेकिन गूगल ने मुझे यहां लाया और सौभाग्य से मैं नोड का उपयोग कर रहा हूं :)
ली गैरी

2
NodeJS केवल सर्वर-साइड केवल समाधान नहीं है। इलेक्ट्रॉन ढांचा डेस्कटॉप अनुप्रयोगों के लिए एक नोडज एम्बेड करता है। यह वास्तव में वह उत्तर है जिसकी मुझे तलाश थी।
एंथनी रेमंड

2
सेमेस्टर यह एक npm पैकेज है, इसे किसी भी JS पर्यावरण पर इस्तेमाल किया जा सकता है! यह सही जवाब है
नीकर

4
@artuska अच्छी तरह से तो बस एक और पैकेज के लिए जाना है जैसे सेमर-तुलना - 233B (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"));

मुझे लगता है कि लाइन: var len = Math.min(a_components.length, b_components.length);कारण संस्करणों 2.0.1.1 और 2.0.1 के बराबर माना जाएगा?
जॉन एगर्टन

1
नहीं, बस लूप के बाद देखो! यदि एक स्ट्रिंग दूसरे का उपसर्ग है (यानी लूप अंत तक पहुंचता है), तो लंबे समय तक अधिक लिया जाता है।
जो

शायद आपने टिप्पणी में अंग्रेजी भाषा पर मेरी ठोकर खा ली थी ...
जो

@ मैं जानता हूँ कि थोड़ा पुराना उत्तर है लेकिन मैं फ़ंक्शन का उपयोग कर रहा था। परीक्षण a = '7'और b = '7.0'रिटर्न -1क्योंकि 7.0 लंबा है। उसके लिए कोई सुझाव मिला? ( console.log(compare("7", "7.0")); //returns -1)
राफेलडीडीएल

मुझे लगता है कि अपरिभाषित व्यवहार के शीर्षक के अंतर्गत आता है। यदि आपके पास ये संस्करण संख्याएं हैं, तो मुझे यकीन है कि आप अपनी आवश्यकताओं को पूरा करने के लिए तर्क को संशोधित कर सकते हैं।
जो

48

यह बहुत छोटा है, फिर भी बहुत तेजी से तुलना फ़ंक्शन किसी भी लंबाई और किसी भी आकार के प्रति खंड के संस्करण संख्या लेता है ।

वापसी मान:
- एक संख्या < 0यदि एक <b
- एक संख्या > 0अगर a> b
- 0यदि a = b है तो

तो आप इसे Array.sort () के लिए फंक्शन की तुलना के रूप में उपयोग कर सकते हैं ;

संपादित करें: "1" और "1.0.0" को समान रूप से पहचानने के लिए बगिफाइड संस्करण स्ट्रिपिंग ज़ीरोस

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"]


'0.0' और '0.0.0' के साथ असफल रहा।
फिडेल

1
@emragins आपको ऐसा करने की आवश्यकता कब होगी?
स्काइलर इटनर

1
@emragins: मैं यह नहीं देखता कि यह कहाँ विफल रहता है। यह आउटपुट करता है ["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"] जहां आपका कोड आउटपुट ["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"] , जो पूरी तरह से समान है, चूंकि 0.0 और 0.0.0 को समान माना जाता है , जिसका अर्थ है कि यह अप्रासंगिक है कि क्या '0.0' '0.0.0' से पहले है या इसके विपरीत।
LeJared

मैं मानता हूं कि यह एक सामान्य बिंदु है। मैं इसे github.com/jonmiles/bootstrap-treeview के साथ उपयोग कर रहा हूं , जो कि संस्करणों के समान तरीके से नोड बनाता है , केवल यह वास्तव में सिर्फ माता-पिता / बच्चे के नोड्स और उनके सूचकांक हैं। पूर्व। माता-पिता: 0.0, बच्चे: 0.0.0, 0.0.1। इस मुद्दे पर अधिक जानकारी के लिए देखें कि मैं क्यों परवाह करता हूं: github.com/jonmiles/bootstrap-treeview/issues/251
emragins

1
यहां देखें उत्तर stackoverflow.com/questions/6611824/why-do-we-need-to-use-radix । यदि निर्दिष्ट नहीं है तो पुराने ब्राउज़र का उपयोग मूलांक पैरामीटर का अनुमान लगाने के लिए किया जाता है। "1.09.12" में मध्य भाग की तरह एक संख्या स्ट्रिंग में एक प्रमुख शून्य, मूलांक = 8 के साथ पार्स किया जाता था, जिसके परिणामस्वरूप अपेक्षित संख्या 9 के बजाय संख्या 0 थी
लेजारेड

14

से लिया 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;
    }

सरल, लेकिन तीन संस्करण क्षेत्रों तक सीमित।
डैन डस्केल्सस्कू

11

मैं यहाँ क्या चाहता था एक समारोह नहीं मिल रहा है। इसलिए मैंने अपना लिखा। यह मेरा योगदान है। मुझे आशा है कि किसी को यह उपयोगी लगता है।

पेशेवरों:

  • संस्करण मनमाने ढंग से लंबाई के तार संभालता है। '1' या '1.1.1.1.1'।

  • निर्दिष्ट न किए जाने पर प्रत्येक मान को 0 में डिफॉल्ट करता है। सिर्फ इसलिए कि एक तार लंबा है इसका मतलब यह नहीं है कि यह एक बड़ा संस्करण है। ('1' '1.0' और '1.0.0.0' के समान होना चाहिए।)

  • संख्याओं की तुलना न करें। ('3' <<21 'सत्य होना चाहिए। असत्य नहीं।)

  • लूप में बेकार की तुलना में समय बर्बाद मत करो। (तुलना के लिए ==)

  • आप अपने खुद के तुलनित्र चुन सकते हैं।

विपक्ष:

  • यह संस्करण स्ट्रिंग में अक्षरों को संभाल नहीं करता है। (मुझे नहीं पता कि यह कैसे काम करेगा?)

जॉन द्वारा स्वीकार किए गए उत्तर के समान मेरा कोड :

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

उदाहरण :

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

स्वीकृत उत्तर में यह संस्करण मेरे विचार से बेहतर है!
user3807877

1
यदि अनियंत्रित उपयोगकर्ता इनपुट के साथ तुलनित्र पैरामीटर का उपयोग किया जाता है तो यह फ़ंक्शन कोड इंजेक्शन के लिए प्रवण होता है! उदाहरण: तुलना ('1.2', '== 0; चेतावनी; ("कोचा");),' 1.2 ');
लेजारेड

@LeJared True। जब मैंने लिखा था कि हम इसे उपयोगकर्ता द्वारा प्रस्तुत कोड के साथ उपयोग नहीं करने जा रहे थे। शायद एक चोर के रूप में इसे लाया जाना चाहिए था। मैंने अब उस संभावना को खत्म करने के लिए कोड अपडेट कर दिया है। अब हालांकि, जब वेबपैक और अन्य नोड.जैस बंडल्स प्रचलित हो गए हैं, तो मैं सुझाव दूंगा कि मोहम्मद अकिदिम का उत्तर ऊपर, सेमेस्टर का उपयोग करते हुए, लगभग हमेशा इस प्रश्न का सही उत्तर होगा।
विक्टर

10

सरल और छोटा कार्य:

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
}

टेस्ट:

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

आप इसे सरल बना सकते हैं: const a = ~~ newParts [i]; वास्तव में यह सबसे कुशल तरीका है जो एक स्ट्रिंग को पूर्णांक में परिवर्तित करता है, जो 0 को लौटाता है यदि चर अपरिभाषित होता है या इसमें गैर-संख्यात्मक अक्षर होते हैं।
Vanowm

5

मुझे माफ कर दो अगर यह विचार पहले से ही एक लिंक में देखा गया है जो मैंने नहीं देखा है।

मुझे भागों को भारित राशि में बदलने में कुछ सफलता मिली है जैसे:

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

जिसने तुलना को बहुत आसान बना दिया (एक दोहरे की तुलना)। हमारे संस्करण क्षेत्र कभी भी 4 अंक से अधिक नहीं होते हैं।

7.10.2.184  -> 7010002184.0
7.11.0.1385 -> 7011001385.0

मुझे आशा है कि यह किसी की मदद करता है, क्योंकि कई स्थितियां थोड़ी अधिक लगती हैं।


2
यह टूट जाएगा, अगर यह। मिनर> 999 (प्रमुख के साथ ओवरलैप होगा)
अफानासी कुराकिन

5

यहाँ एक और छोटा संस्करण है जो किसी भी संख्या में उप संस्करण, गद्देदार शून्य और सम संख्या वाले अक्षरों (1.0.0b3) के साथ काम करता है

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

आउटपुट:

0 : a = b

1 : ए> बी

-1 : ए <बी

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/


5

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

आधुनिक ब्राउज़रों के लिए सबसे सरल कोड:

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

यहां विचार संख्याओं की तुलना करना है लेकिन स्ट्रिंग के रूप में है। तुलनात्मक कार्य करने के लिए दो तार एक ही लंबाई के होने चाहिए। इसलिए:

"123" > "99""123" > "099"
तुलना में "संख्या" को कम करने के लिए पैडिंग करें

यहाँ मैंने प्रत्येक भाग को शून्य के साथ 10. की लंबाई तक पैडिंग किया है, तो बस उत्तर के लिए सरल स्ट्रिंग की तुलना करें

उदाहरण :

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

क्या आप बताएंगे compareVersion2कि वास्तव में क्या होता है?
उस्मान वली

अच्छा है, तो आप बेहतर संगतता के substringबजाय उपयोग कर सकते हैं padStartअर्थात var zeros = "0000000000"; '0.2.32'.split('.').map( s => zeros.substring(0, zeros.length-s.length) + s ).join('.') आपको दे देंगे 0000000000.0000000002.0000000032:)
उस्मान वली


4

मेरे जवाबों में से अधिकांश के मुकाबले मेरी क्रिया कम है

/**
 * 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
}

1
आपको इसे एक मॉड्यूल बनाना चाहिए और इसे नोड पर रखना चाहिए। तब तक, मैं आपके लिए अपने कोड को चोरी के साथ चोरी कर रहा हूं। इसके लिए शुक्रिया।
r3wt

3

हालाँकि इस प्रश्न के पहले से ही बहुत सारे उत्तर हैं, लेकिन हर कोई अपने स्वयं के पिछवाड़े-ब्रूयन समाधान को बढ़ावा देता है, जबकि हमारे पास इसके लिए एक संपूर्ण पारिस्थितिकी तंत्र (लड़ाई-) परीक्षण किए गए पुस्तकालय हैं।

NPM , GitHub , X पर एक त्वरित खोज हमें कुछ प्यारे काम देगा, और मैं कुछ के माध्यम से चलना चाहूंगा:

semver-compareएक महान हल्के (~ 230B) lib विशेष रूप से उपयोगी है कि यदि आप संस्करण संख्याओं द्वारा क्रमबद्ध करना चाहते हैं लाइब्रेरी की उजागर विधि रिटर्न के रूप में, है -1, 0या 1उचित रूप से।

परिवाद का मूल:

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 बल्कि आकार में भारी है (~ 4.4kB gzipped), लेकिन कुछ अच्छे अनूठे तुलनाओं के लिए अनुमति देता है जैसे कि संस्करणों के ढेर / मिनट का अधिकतम पता लगाना या यह पता लगाना कि क्या प्रदान किया गया संस्करण अद्वितीय है या किसी संग्रह में किसी अन्य से कम है संस्करणों।

compare-versionsएक और छोटा काम है (~ 630B gzipped) और अच्छी तरह से कल्पना का अनुसरण करता है, जिसका अर्थ है कि आप अल्फा / बीटा झंडे और यहां तक ​​कि वाइल्डकार्ड (जैसे मामूली / पैच संस्करणों के लिए संस्करणों की तुलना कर सकते हैं: 1.0.xया 1.0.*)

पॉइंट होना: स्टैकऑवरफ्लो से हमेशा कॉपी-पेस्ट कोड की आवश्यकता नहीं होती है, यदि आप अपनी पसंद के पैकेज मैनेजर के माध्यम से सभ्य ((यूनिट-) परीक्षण किए गए संस्करण पा सकते हैं ।


3

मुझे इसी तरह के मुद्दे का सामना करना पड़ा, और मैंने पहले ही इसके लिए एक समाधान तैयार कर लिया था। बेझिझक इसे एक कोशिश दे।

यह रिटर्न 0के लिए equal, 1संस्करण में हैं तो greaterऔर -1अगर यह होता हैless

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


2

विचार दो संस्करणों की तुलना करता है और जानता है कि कौन सा सबसे बड़ा है। हम हटाते हैं "।" और हम वेक्टर की प्रत्येक स्थिति की दूसरे के साथ तुलना करते हैं।

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

महाकाव्य जवाब, वास्तव में मैं क्या देख रहा था।
विंस

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
    }

1
एसओ में आपका स्वागत है। इस प्रश्न के बहुत सारे अच्छे उत्तर पहले से ही हैं, कृपया नए उत्तर जोड़ने से बचें जब तक आप कुछ नया नहीं जोड़ते।
ext

1

replace()समारोह केवल स्ट्रिंग में पहला मामला बदल देता है। तो, के .साथ की जगह देता है ,। बाद में सभी को हटा दें .और फिर ,से .करें और इसे फ्लोट करने के लिए पार्स करें।

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

अंत में, इसे सॉर्ट करें:

versions.sort();

1

इस ब्लॉग पोस्ट को देखें । यह फ़ंक्शन न्यूमेरिक वर्जन नंबरों के लिए काम करता है।

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

1

यदि, उदाहरण के लिए, हम जांचना चाहते हैं कि क्या वर्तमान jQuery संस्करण 1.8 से कम है, parseFloat($.ui.version) < 1.8 )तो गलत परिणाम देगा यदि संस्करण "1.10.1" है, क्योंकि पार्सफ्लोट ("1.10.1") रिटर्न देता है 1.1"1.8" < "1.10"मूल्यांकन के बाद से एक स्ट्रिंग तुलना भी गलत हो जाएगी false

इसलिए हमें इस तरह की परीक्षा की आवश्यकता है

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

निम्न फ़ंक्शन इसे सही ढंग से संभालता है:

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

यहाँ कुछ उदाहरण हैं:

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

लाइव सैंपल और टेस्ट सूट के लिए यहां देखें: http://jsfiddle.net/mar10/8KjvP/


arghh, अभी-अभी देखा कि ripper234 ने कुछ महीने पहले टिप्पणियों पर ईओएफ पर एक फिडेल URL पोस्ट किया था जो काफी समान है। वैसे भी, मैं अपना जवाब यहाँ रखता हूँ ...
mar10

यह इन मामलों में भी विफल हो जाएगा (अधिकांश वेरिएंट के रूप में): versionCompare ('1.09', '1.1') "1" रिटर्न करता है, उसी तरह versionCompare ('1.702', '1.8')।
shaman.sir

कोड "1.09"> "1.1" और "1.702"> "1.8" का मूल्यांकन करता है, जो मुझे लगता है कि सही है। यदि आप सहमत नहीं हैं: क्या आप कुछ संसाधन की ओर इशारा कर सकते हैं जो आपकी राय का समर्थन करता है?
mar10

यह आपके सिद्धांतों पर निर्भर करता है - जैसा कि मुझे पता है कि कोई सख्त नियम या कुछ नहीं है। संसाधनों के बारे में, "इंक्रीमेंटिंग सीक्वेंस" में "सॉफ्टवेयर वर्जनिंग" के लिए विकिपीडिया लेख कहता है कि 1.81 1.8 का मामूली संस्करण हो सकता है, इसलिए 1.8 को 1.80 के रूप में पढ़ा जाना चाहिए। अर्थ वर्जनिंग लेख semver.org/spec/v2.0.0.html भी कहता है कि 1.9.0 -> 1.10.0 -> 1.11.0, इसलिए 1.9.0 को इस तरह की तुलना में 1.90.0 माना जाता है। इसलिए, इस तर्क के बाद, संस्करण 1.702 संस्करण 1.8 से पहले था, जिसे 1.800 के रूप में माना जाता है।
shaman.sir

1
मैं देखता हूं कि कुछ नियम 1.8 <1.81 <1.9 का इलाज करते हैं। लेकिन सेमर में आप 1.81 के बजाय 1.8.1 का उपयोग करेंगे। सेवर (जैसा कि मैं इसे समझता हूं) इस धारणा के आसपास परिभाषित किया गया है कि एक भाग को बढ़ाने से हमेशा एक 'बाद का' संस्करण उत्पन्न होगा, इसलिए 1.8 <1.8.1 <1.9 <1.10 <1.81 <1.90 <1.100। मुझे यह संकेत नहीं दिखता कि यह दो अंकों तक सीमित है। तो मैं कहूंगा कि मेरा कोड पूरी तरह से सेमेस्टर के अनुरूप है।
7:10 पर Mar10

1

यहाँ अन्य उत्तरों से प्रेरित Array.sort के साथ उपयोग के लिए उपयुक्त एक ताबूत कार्यान्वयन यहां दिया गया है:

# 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

यह LeJared के जवाब से प्रेरित है ।
डेन डैस्कलेस्क्यू

यह ठीक से काम नहीं कर रहा है .. यहाँ परिणाम है .. परिणाम ['1.1.1', '2.1.1', '3.3.1.0', '3.1.1.0']
ertan2002

1

मैंने संस्करणों को सॉर्ट करने के लिए एक नोड मॉड्यूल लिखा है, आप इसे यहां पा सकते हैं: संस्करण-सॉर्ट

विशेषताएं :

  • अनुक्रम की कोई सीमा नहीं '1.0.1.5.53.54654.114.1.154.45' काम करता है
  • अनुक्रम लंबाई की कोई सीमा नहीं: '1.1546515465451654654654654138754431574364321353734'
  • संस्करण द्वारा वस्तुओं को सॉर्ट कर सकते हैं (README देखें)
  • चरणों (जैसे अल्फा, बीटा, आरसी 1, आरसी 2)

यदि आपको किसी अन्य सुविधा की आवश्यकता है तो किसी समस्या को खोलने में संकोच न करें।


1

यह किसी अवधि द्वारा अलग किए गए किसी भी लंबाई के संख्यात्मक संस्करणों के लिए काम करता है। यह तभी सही होता है जब myVersion> = minimalVersion होता है, जिससे यह धारणा बनती है कि संस्करण 1 1.0 से कम है, संस्करण 1.1 1.1.0 से कम है और इसी तरह। यह अतिरिक्त शर्तों को जोड़ने के लिए काफी सरल होना चाहिए जैसे कि संख्याओं को स्वीकार करना (बस एक स्ट्रिंग में परिवर्तित करना) और हेक्साडेसिमल या सीमांकक को गतिशील बनाना (बस एक सीमांकक पैरामीटर जोड़ें, फिर "" को परम के साथ बदलें)।

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

यहाँ कुछ परीक्षण दिए गए हैं:

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

वैकल्पिक रूप से यहाँ एक पुनरावर्ती संस्करण है

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

1

मुझे उनकी तुलना करने का एक सरल तरीका मिल गया है, सुनिश्चित करें कि यदि आप चाहते हैं तो यह नहीं है। जब मैं कंसोल में कोड से नीचे चला जाता हूं, तो यह समझ में आता है, और सॉर्ट () विधि का उपयोग करके, मैं संस्करण स्ट्रिंग के सॉर्ट किए गए सरणी को प्राप्त कर सकता हूं। यह वर्णानुक्रम पर आधारित है।

"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"]

3
यह दो अंकों के संस्करण संख्याओं के लिए अच्छी तरह से काम नहीं करता है, उदाहरण के लिए, 1.10.0।
ल्यूकिप

1

आप के String#localeCompareसाथ उपयोग कर सकते हैंoptions

संवेदनशीलता

स्ट्रिंग्स में कौन से अंतरों को गैर-शून्य परिणाम मानों तक ले जाना चाहिए। संभावित मूल्य हैं:

  • "base": केवल अक्षर जो आधार अक्षरों में भिन्न होते हैं, असमान के रूप में तुलना करते हैं। उदाहरण: a ≠ b, a = á, a = A
  • "accent": केवल वे तार जो आधार पत्र या लहजे और अन्य डियाक्रिटिक अंकों में भिन्न होते हैं, असमान के रूप में तुलना करते हैं। उदाहरण: a ≠ b, a ≠ á, a = A
  • "case": आधार पत्र या मामले में भिन्न होने वाले केवल तार असमान के रूप में तुलना करते हैं। उदाहरण: a ≠ b, a = á, a ≠ A
  • "variant": वे तार जो आधार पत्र, लहजे और अन्य डियाक्रिटिक चिह्नों में भिन्न होते हैं, या केस असमान के रूप में तुलना करते हैं। अन्य अंतरों को भी ध्यान में रखा जा सकता है। उदाहरण: a ≠ b, a ≠ á, a ≠ A

डिफ़ॉल्ट "सॉर्ट" उपयोग के लिए "भिन्न" है; यह "खोज" उपयोग के लिए स्थानीय निर्भर है।

संख्यात्मक

क्या संख्यात्मक समतुल्य का उपयोग किया जाना चाहिए, जैसे कि "1" <"2" <"10"। संभावित मूल्य हैं trueऔर false; डिफ़ॉल्ट है false। यह विकल्प एक विकल्प संपत्ति या यूनिकोड एक्सटेंशन कुंजी के माध्यम से सेट किया जा सकता है; यदि दोनों प्रदान किए जाते हैं, तो optionsसंपत्ति पूर्वता लेती है। इस संपत्ति का समर्थन करने के लिए कार्यान्वयन की आवश्यकता नहीं है।

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


यह वास्तव में कैसे काम करता है? undefinedउपरोक्त, भाषा क्या है ? जब आप दूसरों को पढ़ते हैं, तो आप इसे पोस्ट करने के लिए कैसे आते हैं;)
mplungjan

undefinedस्थानीय भाग है, यहाँ उपयोग नहीं किया जाता है।
नीना स्कोल्ज़

0

आप उन्हें संख्याओं में बदल सकते हैं और फिर आकार के बाद क्रमबद्ध कर सकते हैं? उन लोगों के लिए 0 की संख्या जो लंबाई में <4 हैं

सांत्वना में खेला:

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

बड़ा संस्करण, बड़ी संख्या। संपादित करें: संभवतः बड़े संस्करण श्रृंखला के लिए खाते को समायोजित करने की आवश्यकता है


यह सिर्फ एक उदाहरण था, जैसा कि वह खुद कुछ चीजें करने के लिए मिला है: पी 4 के बजाय, सबसे बड़े संस्करण में संख्याओं की मात्रा प्राप्त करें, फिर उन्हें 0 से कम भरें
कंट्रा

0

यह एक साफ सुथरी चाल है। यदि आप विशिष्ट मानों के बीच, संख्यात्मक मानों के साथ काम कर रहे हैं, तो आप संस्करण ऑब्जेक्ट के प्रत्येक स्तर के लिए एक मान निर्दिष्ट कर सकते हैं। उदाहरण के लिए "सबसे बड़ा वाल्यू" यहां 0xFF पर सेट किया गया है, जो आपके संस्करण के लिए बहुत "आईपी" प्रकार बनाता है।

यह अल्फा-न्यूमेरिक वर्जनिंग भी संभालता है (अर्थात 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);

0

मुझे @ mar10 से संस्करण पसंद है , हालांकि मेरे दृष्टिकोण से, गलतफहमी का एक मौका है (ऐसा लगता है कि यह संस्करण नहीं है यदि संस्करण सिमेंटिक संस्करण दस्तावेज़ के साथ संगत हैं , लेकिन मामला हो सकता है यदि कुछ "बिल्ड नंबर" का उपयोग किया जाता है ):

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

यहाँ समस्या यह है कि संस्करण संख्या की उप-संख्याएँ हैं, कुछ मामलों में, अनुगामी शून्य के कट आउट के साथ लिखा गया है (कम से कम जैसा कि मैं हाल ही में विभिन्न सॉफ़्टवेयर का उपयोग करते समय इसे देखता हूं), जो संख्या के तर्कसंगत भाग के समान है, इसलिए:

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

पहला (या दोनों पहला और दूसरा) संस्करण उप-संख्या, हालांकि, हमेशा पूर्णांक मान के रूप में माना जाता है जो वास्तव में इसके बराबर होता है।

यदि आप इस तरह के संस्करण का उपयोग करते हैं, तो आप उदाहरण में कुछ पंक्तियों को बदल सकते हैं:

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

तो पहले एक को छोड़कर हर उप नंबर एक नाव के रूप में की तुलना में किया जाएगा, ताकि 09और 1बन जाएगा 0.09और 0.1तदनुसार और ठीक से इस तरह की तुलना में। 2054और 3हो जाएगा 0.2054और 0.3

पूरा संस्करण तब है, ( @ 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;
}

पुनश्च यह धीमी है, लेकिन यह भी संभव है कि एक ही तुलना करने वाले फ़ंक्शन का पुनः उपयोग करने पर विचार करें कि इस तथ्य को संचालित करने के लिए कि स्ट्रिंग वास्तव में पसंद की सरणी है:

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

0

मैंने इसे Kons विचार के आधार पर बनाया, और जावा संस्करण "1.7.0_45" के लिए इसे अनुकूलित किया। यह सिर्फ एक फंक्शन है जो एक वर्जन स्ट्रिंग को फ्लोट में बदलने के लिए है। यह समारोह है:

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

स्ट्रिंग "1.7.0_45" को 1.0070000450000001 में परिवर्तित किया जाता है और यह सामान्य तुलना के लिए पर्याप्त है। त्रुटि यहां बताई गई है: जावास्क्रिप्ट में फ्लोटिंग पॉइंट नंबर परिशुद्धता से कैसे निपटें? । यदि अधिक की आवश्यकता है तो किसी भी भाग पर 3 अंक आप विभक्त को बदल सकते हैं Math.pow(10, i * 3);

आउटपुट इस तरह दिखेगा:

1.7.0_45         > 1.007000045
ver 1.7.build_45 > 1.007000045
1.234.567.890    > 1.23456789

0

मुझे संस्करण की तुलना की समान समस्या थी, लेकिन संभवतया संस्करणों वाले संस्करणों के साथ (अर्थात: विभाजक जो डॉट्स नहीं थे, आरसी 1, आरसी 2 जैसे एक्सटेंशन ...)।

मैंने इसका उपयोग किया, जो मूल रूप से संख्याओं और गैर-संख्याओं में संस्करण के तारों को विभाजित करता है, और प्रकार के अनुसार तुलना करने की कोशिश करता है।

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

कुछ मामलों के लिए यहां कुछ धारणाएं हैं, उदाहरण के लिए: "1.01" === "1.1", या "1.8" <"1.71"। यह "1.0.0-rc.1" <"1.0.0" को प्रबंधित करने में विफल रहता है, जैसा कि शब्दार्थ संस्करण 2.0.0 द्वारा निर्दिष्ट किया गया है


0

सॉर्ट से पहले के संस्करणों को रोकना मतलब है कि parseInt को कई बार अनावश्यक रूप से नहीं कहा जाता है। माइकल डील के सुझाव के समान एरे # मैप का उपयोग करते हुए, यहां एक प्रकार का उपयोग मैं मानक 3 भाग सेवर के नवीनतम संस्करण को खोजने के लिए करता हूं:

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"

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.