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
, 1
sẽ trở thành 0.09
và 0.1
theo đó và được so sánh đúng theo cách này. 2054
và 3
sẽ trở thành 0.2054
và0.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;
}
}