问题
需要前端从接口返回的版本号列表中,找出最大的版本号。
比如接口返回的版本列表是:
['6.11', '6.11.03', '6.11.03', '6.11.06', '6.11.05', '6.11.07', '6.11.09', '6.12', '6.11.12']
那前端找到的最大版本号是 6.12。
怎么解决?
这里有个问题,一般的版本号主要分为主版本,次版本以及补丁版本。
但这里的版本号是数据库内核版本,所以不一定完全是上面讲的只有三个版本。
有可能是多个分割的数字,比如四个,甚至五个。比如 oracle 的版本号:11.1.0.6.0。
如何通过 js 实现获取到最大的版本号?
很明显,是不能直接把数字之间的点去掉,然后相加对比大小。
因为涉及到补 0 和进位的问题,会比较麻烦。
但从 js 的角度,有一个简单粗暴的方式:
就是可以利用 js 动态语言的特性,把版本号列表都存到对象里面,然后逐一判断,把不符合条件的对象都删掉,剩下的自然就是最大的版本号了。
来段代码练练手:
const data = ['6.11', '6.11.03', '6.11.03', '6.11.06', '6.11.05', '6.11.07', '6.11.09', '6.12', '6.11.12'] function getMaxVersion(data) { // 先把版本信息整理成对象,对象的值是各个版本号组成的数组。比如 6.11,则 versionObj['6.11'] = ['6', '11'] const versionObj = {} // 同时计算对象值数组的长度,下面遍历要以最大长度来循环 let maxLength = 0 for (let i = 0; i < data.length; i++) { versionObj[data[i]] = [] let length = 0 data[i].split('.').forEach((element) => { length++ versionObj[data[i]].push(element) }) if (length > maxLength) { maxLength = length } } let maxValue = null // 把对象的值每一个数组项都对比判断,得出当前数组项的最大值,然后把小于最大值的对象都删了,剩下的便是最大值的对象了 // 比如 versionObj['6.11.03'] = ['6', '11', '03'],则判断 6,然后再判断 11,,然后再判断 03,以此类推。 for (let j = 0; j < maxLength; j++) { for (let option in versionObj) { // maxValue 第一次肯定是 null,此时把第一个对象的值默认为 maxValue if (maxValue === null) { // 对象的值在对应的数组中可能没有,也就是 undefined,那就需要给个 0,好对比判断 maxValue = versionObj[option][j] ? versionObj[option][j] : 0 } else { // 然后跟其他的值对比,如果大于 maxValue,则赋值给 maxValue。以便当前循环结束后,maxValue 就是最大值 if ((versionObj[option][j] ? versionObj[option][j] : 0) > maxValue) { maxValue = versionObj[option][j] ? versionObj[option][j] : 0 } } } // 然后再循环判断,把所有小于 maxValue 的对象都删了,剩下的便是最大值的对象了 for (let option in versionObj) { if ((versionObj[option][j] ? versionObj[option][j] : 0) < maxValue) { delete versionObj[option] } } // 每次循环结束都重置为 null,保证新的循环开始的第一次都是 null maxValue = null } let result = [] for (let option in versionObj) { // 对象仅剩一个值了,直接取就可以 result = versionObj[option] } // 如果 result 没有值,则取版本列表的第一个 return result.join('.') ? result.join('.') : data[0] } console.log(getMaxVersion(data)) // 6.12
虽然上述代码可以实现效果。
但是,是不是觉得有点不够优雅?是不是觉得复杂繁琐了?
巧妙的方式呢?
不要老想着怎么对版本号进行分割、拼接甚至比较判断。
其实可以换个思路:
比如先排序,然后直接获取排序后的第一个值,不就是可以巧妙的获取到最大的版本号了吗?
代码如下:
const data = ['6.11', '6.11.03', '6.11.03', '6.11.06', '6.11.05', '6.11.07', '6.11.09', '6.12', '6.11.12']; function sortVersion(data) { const result = data.sort(function (a, b) { // 先分割为数组 let aParts = a.split('.') let bParts = b.split('.') const len = Math.max(aParts.length, bParts.length) // 然后再比较当前数组的所有部分,直到找到不同的部分或者数组末尾 for (let i = 0; i < len; i++) { let aNext = i < aParts.length ? parseInt(aParts[i]) : 0 let bNext = i < bParts.length ? parseInt(bParts[i]) : 0 if (aNext < bNext) { // 降序排列 return 1 } if (aNext > bNext) { return -1 } } // 如果都相同,则返回 0,表示两个版本号相等 return 0 }) return result } console.log(sortVersion(data)[0]