ฉันชอบรุ่นจาก@ 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;
}
PS มันช้าลง แต่ก็เป็นไปได้ที่จะคิดเกี่ยวกับการใช้ฟังก์ชั่นการเปรียบเทียบเดียวกันอีกครั้งในการดำเนินงานความจริงที่ว่าสตริงนั้นเป็นอาร์เรย์ของตัวอักษร:
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;
}
}