Làm thế nào để so sánh số phiên bản phần mềm bằng js? (chỉ số)


164

Đây là số phiên bản phần mềm:

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

Làm thế nào tôi có thể so sánh điều này ?? Giả sử thứ tự đúng là:

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

Ý tưởng rất đơn giản ...: Đọc chữ số đầu tiên, hơn, thứ hai, sau đó là số thứ ba .... Nhưng tôi không thể chuyển đổi số phiên bản thành số nổi .... Bạn cũng có thể thấy số phiên bản như điều này:

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

và điều này rõ ràng hơn để xem ý tưởng đằng sau là gì ... Nhưng, làm thế nào để chuyển đổi nó thành một chương trình máy tính ?? Có ai có bất kỳ ý tưởng về cách sắp xếp này? Cảm ơn bạn.


5
Đây sẽ là một câu hỏi phỏng vấn loại fizzbuzz tốt.
Steve Claridge

2
Đây là lý do tại sao tất cả các số phiên bản phần mềm phải là số nguyên như 2001403. Khi bạn muốn hiển thị nó theo một cách thân thiện như "2.0.14.3" thì bạn định dạng số phiên bản tại thời điểm thuyết trình.
jarmod

2
Vấn đề chung ở đây là so sánh Phiên bản ngữ nghĩa và nó không tầm thường (xem # 11 tại semver.org ). May mắn thay, có một thư viện chính thức cho điều đó, phiên bản ngữ nghĩa cho npm .
Dan Dascalescu

1
Tìm thấy một tập lệnh đơn giản so sánh các semvers
vsync

Câu trả lời:


133

Ý tưởng cơ bản để thực hiện so sánh này sẽ là sử dụng Array.splitđể lấy các mảng của các phần từ chuỗi đầu vào và sau đó so sánh các cặp phần từ hai mảng; nếu các phần không bằng nhau, chúng ta biết phiên bản nào nhỏ hơn.

Có một vài chi tiết quan trọng cần ghi nhớ:

  1. Làm thế nào các bộ phận trong mỗi cặp nên được so sánh? Câu hỏi muốn so sánh bằng số, nhưng nếu chúng ta có các chuỗi phiên bản không được tạo thành chỉ bằng các chữ số (ví dụ: "1.0a") thì sao?
  2. Điều gì sẽ xảy ra nếu một chuỗi phiên bản có nhiều phần hơn các chuỗi khác? Nhiều khả năng "1.0" nên được coi là ít hơn "1.0.1", nhưng còn "1.0.0" thì sao?

Đây là mã để triển khai mà bạn có thể sử dụng trực tiếp ( ý chính với tài liệu ):

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

Phiên bản này so sánh các phần một cách tự nhiên , không chấp nhận hậu tố ký tự và coi "1.7" nhỏ hơn "1.7.0". Chế độ so sánh có thể được thay đổi thành từ điển và chuỗi phiên bản ngắn hơn có thể được tự động đệm bằng cách sử dụng đối số thứ ba tùy chọn.

Có một JSFiddle chạy "kiểm tra đơn vị" ở đây ; nó là một phiên bản hơi mở rộng của công việc của ripper234 (cảm ơn bạn).

Lưu ý quan trọng: Mã này sử dụng Array.mapArray.every, có nghĩa là nó sẽ không chạy trong các phiên bản IE sớm hơn 9. Nếu bạn cần hỗ trợ những mã này, bạn sẽ phải cung cấp polyfill cho các phương thức bị thiếu.


16
Đây là phiên bản cải tiến với một số bài kiểm tra đơn vị: jsfiddle.net/ripper234/Xv9WL/28
ripper234

5
Xin chào, tôi đã đưa ý chính này vào một bài kiểm tra với tất cả các bài kiểm tra và mọi thứ và đưa nó lên npm và bower để tôi có thể đưa nó vào các dự án của mình dễ dàng hơn. github.com/gabe0x02/version_compare
Gabriel Littman

2
@GabrielLittman: Này, cảm ơn vì đã dành thời gian để làm điều đó! Tuy nhiên, tất cả mã trên SO được cấp phép với CC-BY-SA theo mặc định. Điều đó có nghĩa là bạn không thể có gói của bạn được cấp phép GPL. Tôi biết lập pháp không phải là bất cứ ai ở đây, nhưng sẽ tốt nếu bạn sửa nó.
Jon

2
@GabrielLittman: GPL thực sự rất hạn chế theo nghĩa là bạn buộc phải cấp phép GPL tất cả các mã tiếp xúc với mã GPL hiện có. Dù sao, để tham khảo trong tương lai: một giấy phép "làm bất cứ điều gì bạn muốn, được sử dụng rộng rãi" là MIT .
Jon

3
@GabrielLittman: đã có những thư viện được thành lập được viết bởi các nhà phát triển dày dạn thực hiện so sánh semver.
Dan Dascalescu

82

học kỳ

Trình phân tích cú pháp phiên bản ngữ nghĩa được sử dụng bởi npm.

$ npm cài đặt 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, '*')

Liên kết phiên bản ngữ nghĩa :
https://www.npmjs.com/package/semver#prerelease-identifier


8
Đúng. Đây là câu trả lời đúng - so sánh các phiên bản là không tầm thường (xem # 11 tại semver.org ) và có các thư viện cấp sản xuất thực hiện công việc.
Dan Dascalescu

7
về mặt kỹ thuật, đây không phải là câu trả lời đúng, vì node.js và javascript khác nhau. Tôi cho rằng câu hỏi ban đầu được nhắm mục tiêu nhiều hơn cho trình duyệt. Nhưng google đã đưa tôi đến đây và may mắn là tôi đang sử dụng nút :)
Lee Gary

2
NodeJS không chỉ là giải pháp phía máy chủ. Khung điện tử nhúng một nútJS cho các ứng dụng máy tính để bàn. Đây thực sự là câu trả lời tôi đang tìm kiếm.
Anthony Raymond

2
semver đó là một gói npm, nó có thể được sử dụng trên bất kỳ môi trường JS nào! Đây là câu trả lời đúng
neiker

4
@artuska tốt rồi, chỉ cần đi một gói khác như so sánh semver - 233B (dưới 0,5kB!) đã được nén :)
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"));

Tôi nghĩ rằng dòng: var len = Math.min(a_components.length, b_components.length);sẽ làm cho các phiên bản 2.0.1.1 và 2.0.1 được coi là như nhau?
Jon Egerton

1
Không. Chỉ nhìn sau vòng lặp! Nếu một chuỗi là tiền tố của chuỗi khác (tức là vòng lặp đến cuối), thì chuỗi dài hơn được lấy càng cao.
Joe

Có lẽ bạn đã bỏ qua sự vấp ngã của tôi về ngôn ngữ tiếng Anh trong bình luận ...
Joe

@Joe Tôi biết là một câu trả lời hơi cũ nhưng tôi đã sử dụng chức năng. Kiểm tra a = '7'b = '7.0'trả về -1vì 7.0 dài hơn. Có bất cứ đề nghị cho điều đó? ( console.log(compare("7", "7.0")); //returns -1)
RaphaelDDL

Tôi cho rằng điều đó xuất hiện dưới tiêu đề của hành vi không xác định. Nếu bạn có những số phiên bản này thì tôi chắc chắn bạn có thể sửa đổi logic để phù hợp với yêu cầu của bạn.
Joe

48

Hàm so sánh rất nhỏ nhưng rất nhanh này lấy số phiên bản có độ dài bất kỳbất kỳ kích thước số nào trên mỗi phân đoạn .

Trả về giá trị:
- một số < 0nếu a <b
- một số > 0nếu a> b
- 0nếu a = b

Vì vậy, bạn có thể sử dụng nó làm hàm so sánh cho Array.sort ();

EDIT: Phiên bản có lỗi tước các số 0 ở cuối để nhận ra "1" và "1.0.0" bằng nhau

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


Thất bại với '0,0' và '0,0.0'. Xem fiddle: jsfiddle.net/emragins/9e9pweqg
emragins

1
@emragins Khi nào bạn cần làm điều đó?
Skylar Ittner

1
@emragins: Tôi không thấy nó thất bại ở đâu. Nó xuất ra ["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"] nơi mã đầu ra của bạn ["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"] , hoàn toàn giống nhau, vì 0,0 và 0,0.0 được coi là bằng nhau , điều đó có nghĩa là không liên quan cho dù '0,0' là trước '0,0.0' hay ngược lại.
LeJared

Tôi đồng ý đây là một điểm thông thường. Tôi đang sử dụng điều này với github.com/jonmiles/bootstrap-treeview , điều chỉnh các nút theo cách tương tự như các phiên bản, chỉ thực sự nó chỉ là các nút cha / con và các chỉ mục của chúng. Ví dụ. Cha mẹ: 0,0, con: 0,0.0, 0,0.1. Xem vấn đề này để biết thêm chi tiết về lý do tại sao tôi quan tâm: github.com/jonmiles/bootstrap-treeview/issues/251
emragins

1
Xem câu trả lời tại đây stackoverflow.com/questions/6611824/why-do-we-need-to-use-radix . Các trình duyệt cũ hơn được sử dụng để đoán tham số cơ số nếu không được chỉ định. Số 0 đứng đầu trong chuỗi số như phần giữa trong "1.09.12" được sử dụng để được phân tích cú pháp với radix = 8 dẫn đến số 0 thay vì số dự kiến ​​9.
LeJared

14

Lấy từ 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;
    }

Đơn giản, nhưng giới hạn trong ba lĩnh vực phiên bản.
Dan Dascalescu

11

Không thể tìm thấy một chức năng làm những gì tôi muốn ở đây. Vì vậy, tôi đã viết của riêng tôi. Đây là đóng góp của tôi. Tôi hy vọng ai đó thấy nó hữu ích.

Ưu điểm:

  • Xử lý chuỗi phiên bản có độ dài tùy ý. '1' hoặc '1.1.1.1.1'.

  • Mặc định mỗi giá trị là 0 nếu không được chỉ định. Chỉ vì một chuỗi dài hơn không có nghĩa đó là một phiên bản lớn hơn. ('1' phải giống với '1.0' và '1.0.0.0'.)

  • So sánh số không phải chuỗi. ('3' <'21' nên đúng. Không sai.)

  • Đừng lãng phí thời gian vào những so sánh vô dụng trong vòng lặp. (So ​​sánh với ==)

  • Bạn có thể chọn so sánh của riêng bạn.

Nhược điểm:

  • Nó không xử lý các chữ cái trong chuỗi phiên bản. (Tôi không biết làm thế nào mà thậm chí sẽ làm việc?)

Mã của tôi, tương tự như câu trả lời được chấp nhận bởi 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);
}

Ví dụ :

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

Theo tôi, phiên bản này tốt hơn phiên bản đã được phê duyệt!
3807877

1
Hàm này dễ bị tiêm mã nếu tham số bộ so sánh được sử dụng với đầu vào người dùng không được kiểm tra! Ví dụ: soVersions ('1.2', '== 0; alert ("cotcha");', '1.2');
LeJared

@LeJared Đúng. Khi tôi viết nó, chúng tôi sẽ không sử dụng nó với mã người dùng gửi. Có lẽ nên mang nó lên như một con lừa. Bây giờ tôi đã cập nhật mã để loại bỏ khả năng đó. Bây giờ, mặc dù, khi gói webpack và các gói node.js khác trở nên phổ biến, tôi sẽ đề xuất rằng câu trả lời của Mohammed Akdim ở trên, sử dụng semver, hầu như sẽ luôn là câu trả lời chính xác cho câu hỏi này.
Viktor

10

Chức năng đơn giản và ngắn gọn:

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
}

Các xét nghiệm:

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

Bạn có thể đơn giản hóa nó bằng: const a = ~ ~ newParts [i]; Trong thực tế, đây là cách hiệu quả nhất để chuyển đổi một chuỗi thành một số nguyên, trả về 0 nếu biến không xác định hoặc chứa các ký tự không phải là số.
vanowm

5

Hãy tha thứ cho tôi nếu ý tưởng này đã được truy cập trong một liên kết mà tôi chưa thấy.

Tôi đã có một số thành công với việc chuyển đổi các phần thành một tổng có trọng số như vậy:

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

Mà thực hiện so sánh rất dễ dàng (so sánh một đôi). Các trường phiên bản của chúng tôi không bao giờ quá 4 chữ số.

7.10.2.184  -> 7010002184.0
7.11.0.1385 -> 7011001385.0

Tôi hy vọng điều này sẽ giúp được ai đó, vì nhiều điều kiện có vẻ hơi quá mức.


2
Điều này sẽ phá vỡ, nếu this.minor> 999 (sẽ trùng với chính)
Afanasii Kurakin

5

Đây là một phiên bản ngắn khác hoạt động với bất kỳ số lượng phiên bản phụ, số không đệm và số chẵn có chữ cái (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;
}

Đầu ra:

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/


5

Câu trả lời năm 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;
    }

Mã đơn giản nhất cho các trình duyệt hiện đại:

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

Ý tưởng ở đây là so sánh các số nhưng ở dạng chuỗi. để làm cho công việc so sánh, hai chuỗi phải có cùng độ dài. vì thế:

"123" > "99" trở nên "123" > "099"
đệm số ngắn "sửa" so sánh

Ở đây tôi đệm từng phần bằng 0 đến độ dài 10. sau đó chỉ cần sử dụng chuỗi đơn giản so sánh cho câu trả lời

Thí dụ :

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

bạn sẽ giải thích chức năng compareVersion2chính xác những gì xảy ra?
Usman Wali

Tốt, sau đó bạn có thể sử dụng substringthay vì padStartđể tương thích tốt hơn tức là var zeros = "0000000000"; '0.2.32'.split('.').map( s => zeros.substring(0, zeros.length-s.length) + s ).join('.') sẽ cung cấp cho bạn 0000000000.0000000002.0000000032:)
Usman Wali


4

Câu trả lời ít dài dòng của tôi hơn hầu hết các câu trả lời ở đây

/**
 * 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
bạn nên biến nó thành một mô-đun và đặt nó vào node.js. cho đến lúc đó, tôi đang đánh cắp mã của bạn với sự quy kết cho bạn. cảm ơn vì điều này.
r3wt

3

Mặc dù câu hỏi này đã có rất nhiều câu trả lời, nhưng mỗi câu hỏi đều thúc đẩy giải pháp sân sau của riêng họ, trong khi chúng ta có cả một hệ sinh thái gồm các thư viện được thử nghiệm (trận chiến) cho việc này.

Tìm kiếm nhanh trên NPM , GitHub , X sẽ cung cấp cho chúng tôi một số lib đáng yêu và tôi muốn lướt qua một số:

semver-comparelà một lib nhẹ (~ 230B) tuyệt vời đặc biệt hữu ích nếu bạn muốn sắp xếp theo số phiên bản, khi phương thức tiếp xúc của thư viện trả về -1, 0hoặc 1một cách thích hợp.

Cốt lõi của lib:

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 có kích thước khá lớn (~ 4,4kB được nén), nhưng cho phép một số so sánh độc đáo đẹp mắt để tìm min / max của một chồng phiên bản hoặc để tìm hiểu xem phiên bản được cung cấp là duy nhất hay ít hơn bất kỳ thứ gì khác trong bộ sưu tập phiên bản.

compare-versionslà một lib nhỏ khác (~ 630B được nén) và tuân theo thông số kỹ thuật độc đáo, có nghĩa là bạn có thể so sánh các phiên bản với cờ alpha / beta và thậm chí cả ký tự đại diện (như đối với các phiên bản nhỏ / vá: 1.0.xhoặc1.0.* )

Điểm đang tồn tại: không phải lúc nào cũng cần sao chép-dán mã từ StackOverflow, nếu bạn có thể tìm thấy các phiên bản thử nghiệm (đơn vị-) đàng hoàng thông qua trình quản lý gói lựa chọn của bạn.


3

Tôi đã đối mặt với vấn đề tương tự, và tôi đã tạo ra một giải pháp cho nó. Hãy thử xem.

Nó sẽ trả về 0cho equal, 1nếu phiên bản là greater-1nếu nó là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

Ý tưởng là so sánh hai phiên bản và biết cái nào là lớn nhất. Chúng tôi xóa "." và chúng ta so sánh từng vị trí của vectơ với nhau.

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

Câu trả lời sử thi, chính xác những gì tôi đang tìm kiếm.
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
    }

1
Chào mừng đến với SO. Câu hỏi này đã có rất nhiều câu trả lời hay, xin vui lòng không thêm câu trả lời mới trừ khi bạn thêm câu trả lời mới.
ext

1

Các replace()chức năng chỉ thay thế sự xuất hiện đầu tiên trong chuỗi. Vì vậy, hãy thay thế .bằng ,. Sau đó xóa tất cả .và làm ,cho .một lần nữa và phân tích nó để nổi.

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

cuối cùng, sắp xếp nó:

versions.sort();

1

Kiểm tra bài blog này . Hàm này hoạt động cho số phiên bản số.

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

Ví dụ: nếu chúng tôi muốn kiểm tra xem phiên bản jQuery hiện tại có nhỏ hơn 1.8 không, parseFloat($.ui.version) < 1.8 )sẽ cho kết quả sai nếu phiên bản là "1.10.1", vì parseFloat ("1.10.1") trả về 1.1. Một so sánh chuỗi cũng sẽ sai, vì "1.8" < "1.10"đánh giáfalse .

Vì vậy, chúng tôi cần một bài kiểm tra như thế này

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

Hàm sau xử lý chính xác điều này:

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

Dưới đây là một số ví dụ:

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

Xem tại đây để xem mẫu và bộ thử nghiệm trực tiếp: http://jsfiddle.net/mar10/8KjvP/


arghh, chỉ cần lưu ý rằng ripper234 đã đăng một URL bí mật trên eof các ý kiến ​​một vài tháng trước đó là khá giống nhau. Dù sao, tôi vẫn giữ câu trả lời của mình ở đây ...
mar10

Điều này cũng sẽ thất bại (như hầu hết các biến thể xung quanh) trong các trường hợp sau: versionCompare ('1.09', '1.1') trả về "1", giống như phiên bảnCompare ('1.702', '1.8').
shaman.sir

Mã đánh giá "1.09"> "1.1" và "1.702"> "1.8", mà tôi nghĩ là chính xác. Nếu bạn không đồng ý: bạn có thể chỉ ra một số tài nguyên ủng hộ ý kiến ​​của bạn không?
mar10

Nó phụ thuộc vào nguyên tắc của bạn - như tôi biết không có quy tắc nghiêm ngặt hay điều gì. Về tài nguyên, bài viết trên wikipedia cho "Phiên bản phần mềm" trong "Trình tự tăng dần" nói rằng 1.81 có thể là phiên bản nhỏ của 1.8, vì vậy 1.8 nên đọc là 1.80. Bài viết phiên bản ngữ nghĩa semver.org/spec/v2.0.0.html cũng nói rằng 1.9.0 -> 1.10.0 -> 1.11.0, vì vậy 1.9.0 được coi là 1.90.0 so với như thế này. Vì vậy, theo logic này, phiên bản 1.702 đã có trước phiên bản 1.8, được coi là 1.800.
shaman.sir

1
Tôi thấy rằng một số quy tắc xử lý 1.8 <1.81 <1.9. Nhưng trong học kỳ, bạn sẽ sử dụng 1.8.1 thay vì 1.81. Semver (theo tôi hiểu) được định nghĩa xung quanh giả định rằng việc tăng một phần sẽ luôn tạo ra phiên bản 'sau', vì vậy 1.8 <1.8.1 <1.9 <1.10 <1.81 <1.90 <1.100. Tôi cũng không thấy một dấu hiệu nào cho thấy điều này bị giới hạn ở hai chữ số. Vì vậy, tôi sẽ nói rằng mã của tôi hoàn toàn phù hợp với semver.
mar10

1

Đây là một triển khai coffeescript phù hợp để sử dụng với Array.sort lấy cảm hứng từ các câu trả lời khác tại đây:

# 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

Điều này được lấy cảm hứng từ câu trả lời của LeJared .
Dan Dascalescu

điều này không hoạt động đúng .. đây là kết quả .. kết quả ['1.1.1', '2.1.1', '3.3.1.0', '3.1.1.0']
ertan2002

1

Tôi đã viết một mô-đun nút để sắp xếp các phiên bản, bạn có thể tìm thấy nó ở đây: phiên bản sắp xếp

Các tính năng :

  • không giới hạn trình tự '1.0.1.5.53.54654.114.1.154.45' hoạt động
  • không giới hạn độ dài chuỗi: '1.1546515465451654654654654138754431574364321353734' hoạt động
  • có thể sắp xếp các đối tượng theo phiên bản (xem README)
  • các giai đoạn (như alpha, beta, rc1, rc2)

Đừng ngần ngại mở một vấn đề nếu bạn cần một tính năng khác.


1

Điều này hoạt động cho các phiên bản số có độ dài bất kỳ cách nhau bởi một khoảng thời gian. Nó chỉ trả về true nếu myVersion là> = minimVersion, giả định rằng phiên bản 1 nhỏ hơn 1.0, phiên bản 1.1 nhỏ hơn 1.1.0, v.v. Sẽ khá đơn giản để thêm các điều kiện bổ sung như chấp nhận số (chỉ cần chuyển đổi thành chuỗi) và thập lục phân hoặc làm cho dấu phân cách động (chỉ cần thêm tham số dấu phân cách sau đó thay thế "." Bằng param)

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

Dưới đây là một số bài kiểm tra:

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

Hoặc ở đây là một phiên bản đệ quy

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

Tôi tìm thấy một cách đơn giản nhất để so sánh chúng, không chắc đó có phải là điều bạn muốn không. Khi tôi chạy mã bên dưới trong bảng điều khiển, nó có ý nghĩa và sử dụng phương thức sort (), tôi có thể nhận được chuỗi các phiên bản đã sắp xếp. nó dựa trên thứ tự bảng chữ cái.

"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
Nó không hoạt động tốt cho các số phiên bản hai chữ số, ví dụ: 1.10.0.
Leukipp

1

Bạn có thể sử dụng String#localeComparevớioptions

nhạy cảm

Sự khác biệt nào trong chuỗi sẽ dẫn đến giá trị kết quả khác không. Các giá trị có thể là:

  • "base": Chỉ các chuỗi khác nhau trong các chữ cái cơ sở so sánh là không bằng nhau. Ví dụ: a ≠ b, a = á, a = A.
  • "accent": Chỉ các chuỗi khác nhau về chữ cái hoặc dấu trọng âm và các dấu phụ khác so sánh là không bằng nhau. Ví dụ: a ≠ b, a ≠ á, a = A.
  • "case": Chỉ các chuỗi khác nhau trong các chữ cái cơ sở hoặc trường hợp so sánh là không bằng nhau. Ví dụ: a ≠ b, a = á, a ≠ A.
  • "variant": Các chuỗi khác nhau trong các chữ cái cơ bản, dấu trọng âm và các dấu phụ khác hoặc trường hợp so sánh là không bằng nhau. Sự khác biệt khác cũng có thể được xem xét. Ví dụ: a ≠ b, a ≠ á, a ≠ A.

Mặc định là "biến thể" để sử dụng "sắp xếp"; đó là địa phương phụ thuộc vào việc sử dụng "tìm kiếm".

số

Có nên sử dụng đối chiếu số hay không, sao cho "1" <"2" <"10". Các giá trị có thể là truefalse; mặc định là false. Tùy chọn này có thể được đặt thông qua thuộc tính tùy chọn hoặc thông qua khóa mở rộng Unicode; nếu cả hai được cung cấp, optionstài sản được ưu tiên. Triển khai không bắt buộc để hỗ trợ tài sản này.

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


Làm thế nào điều này thực sự hoạt động? Là những gì undefinedở trên, ngôn ngữ? Tại sao bạn quản lý để đăng bài này trong khi tôi đọc những người khác;)
mplungjan

undefinedlà phần địa phương, không được sử dụng ở đây.
Nina Scholz

0

bạn không thể chuyển đổi chúng thành số và sau đó sắp xếp theo kích thước? Nối 0 vào các số có độ dài <4

chơi xung quanh trong giao diện điều khiển:

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

phiên bản càng lớn, số lượng càng lớn. Chỉnh sửa: có thể cần điều chỉnh để chiếm tài khoản cho loạt phiên bản lớn hơn


Đó chỉ là một ví dụ, khi anh ấy phải tự mình làm một số việc: P Thay vì 4, hãy lấy số lượng mà phiên bản lớn nhất có, sau đó điền vào những số thấp hơn bằng 0
Contra

0

Đây là một mẹo gọn gàng. Nếu bạn đang xử lý các giá trị số, giữa một phạm vi giá trị cụ thể, bạn có thể gán giá trị cho từng cấp của đối tượng phiên bản. Ví dụ: "LargeValue" được đặt thành 0xFF tại đây, điều này tạo ra một kiểu rất "IP" cho phiên bản của bạn.

Điều này cũng xử lý phiên bản alpha-số (tức là 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

Tôi thích phiên bản từ @ mar10 , mặc dù theo quan điểm của tôi, có thể có sự nhầm lẫn (có vẻ như không phải là trường hợp nếu các phiên bản tương thích với tài liệu Phiên bản ngữ nghĩa , nhưng có thể là trường hợp nếu một số "số bản dựng" được sử dụng ):

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

Vấn đề ở đây là số phụ của số phiên bản, trong một số trường hợp, được viết bằng các số 0 bị cắt ra (ít nhất là gần đây tôi thấy nó trong khi sử dụng phần mềm khác nhau), tương tự như phần hợp lý của một số, vì vậy:

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

Tuy nhiên, số phụ phiên bản thứ nhất (hoặc cả thứ hai và thứ hai) luôn được coi là một giá trị nguyên mà nó thực sự bằng.

Nếu bạn sử dụng loại phiên bản này, bạn có thể thay đổi chỉ một vài dòng trong ví dụ:

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

Vì vậy, mọi số phụ trừ số đầu tiên sẽ được so sánh như một số float, do đó 09, 1sẽ trở thành 0.090.1theo đó và được so sánh đúng theo cách này. 20543sẽ trở thành 0.20540.3 .

Phiên bản hoàn chỉnh sau đó là (tín dụng cho @ 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 chậm hơn, nhưng cũng có thể nghĩ đến việc sử dụng lại chức năng so sánh tương tự điều hành thực tế là chuỗi thực sự là mảng các ký tự:

 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

Tôi đã thực hiện điều này dựa trên ý tưởng của Kons và tối ưu hóa nó cho phiên bản Java "1.7.0_45". Đây chỉ là một chức năng có nghĩa là chuyển đổi một chuỗi phiên bản thành một float. Đây là chức năng:

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

Chuỗi "1.7.0_45" được chuyển đổi thành 1.0070000450000001 và điều này đủ tốt để so sánh bình thường. Lỗi được giải thích ở đây: Làm thế nào để đối phó với độ chính xác của số dấu phẩy động trong JavaScript? . Nếu cần nhiều hơn 3 chữ số trên bất kỳ phần nào, bạn có thể thay đổi dải phân cách Math.pow(10, i * 3);.

Đầu ra sẽ như thế này:

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

0

Tôi có cùng một vấn đề so sánh phiên bản, nhưng với các phiên bản có thể chứa bất cứ thứ gì (ví dụ: dấu phân cách không phải là dấu chấm, phần mở rộng như RC1, RC2 ...).

Tôi đã sử dụng cái này, về cơ bản phân tách các chuỗi phiên bản thành số và không số và cố gắng so sánh tương ứng với loại.

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

Có một số giả định ở đây cho một số trường hợp, ví dụ: "1.01" === "1.1" hoặc "1.8" <"1.71". Không thể quản lý "1.0.0-rc.1" <"1.0.0", như được chỉ định bởi phiên bản Semantic 2.0.0


0

Tiền xử lý các phiên bản trước khi sắp xếp có nghĩa là parseInt không được gọi nhiều lần không cần thiết. Sử dụng bản đồ Array # tương tự như đề xuất của Michael Deal, đây là một loại tôi sử dụng để tìm phiên bản mới nhất của một học kỳ 3 phần tiêu chuẩn:

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"

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.