昨天遇到一个笔试题,本来我想的很简单,可是真的做了才知道自己的不足(我知道自己很菜,但是我会将这些挫折一点点累积起来,相信会越来越强,哪怕比别人慢很多,也不要放弃)

题目是:请用您熟悉的编程语言,编程实现一个比较任意两个软件版本号大小的函数,如 1.2.3a 和 1.2.4b 比较,后者版本号更大,请考虑各种情况,不可以使用系统提供的比较函数。

我首先想到根据'.'分开,逐个判断。
后来百度时发现更简单的方法是,将所有以'.'分开的分组补'0',让所有位数相同,再组合在一起。即'1.10.3'变成'000100100003',再进行比较。

这是我的答案,里面很多错误(难受)

const version1 = '1.2.3a'
const version2 = '1.2.3b'
const version3 = '1.2.4a'
const version4 = '1.3.3a'
const version5 = '2.2.3a'

const contrast=(num1,num2)=>{
    //判断传入数据的类型
    if(Object.prototype.toString.call(num1) !== "[object String]" || Object.prototype.toString.call(num2) !== "[object String]")return 'error'
    
    //根据‘.’分成数组
    let arr1 =num1.split('.'),
        arr2 =num2.split('.')
   
    //如果数组长度不是3 证明格式不对
    if(arr1.length !== 3 || arr2.length !==3 )return 'error'

    //如果第一位和第二位不是纯数字,则格式错误
    if(!numberCheck(arr1[0]) ||!numberCheck(arr1[1]) || !numberCheck(arr2[0]) || !numberCheck(arr2[1]))return 'error'
    
    //判断num1和num2第三位是否是数字和字母的混合,未考虑乱写如‘1a2b3ccc’这种
    if(/^[\da-zA-Z]*$/g.test(arr1[2]) && /^[\da-zA-Z]*$/g.test(arr2[2])){
        //将第三位改成纯数字,添加一个纯字母
        arr1.push(arr1[2].replace(/\d/g,''))
        arr1[2] = parseInt(arr1[2])
        arr2.push(arr2[2].replace(/\d/g,''))
        arr2[2] = parseInt(arr2[2])
    }
    //遍历的次数
    const l = arr1.length
    //遍历两个版本号,由于限制版本号的格式,所以长度为3    
    for(let i = 0; i < l; i++){
      //按照顺序,从第一位开始,校验到第三位
      if(arr1[i]>arr2[i]){  
        //如果num1第i位的值大。num1版本号就大
        return `${num1} > ${num2}` 
      }else if(arr1[i]!==arr2[i]){
        //如果不等且不大
        return `${num1} < ${num2}` 
      }
    }

    return `${num1} = ${num2}` 
}

const numberCheck = (num) => {
    return /^\d*$/g.test(num)
}

console.log(`1和2对比:${contrast(version1,version2)}`)
console.log(`1和3对比:${contrast(version1,version3)}`)
console.log(`1和4对比:${contrast(version1,version4)}`)
console.log(`1和5对比:${contrast(version1,version5)}`)

//1和2对比:1.2.3a > 1.2.3b
//1和3对比:1.2.3a < 1.2.4a
//1和4对比:1.2.3a < 1.3.3a
//1和5对比:1.2.3a < 2.2.3a

复制代码

首先,在被面试官否定的时候,我回顾代码第一个发现的错误:
对比版本号'1.2.3a'和'1.10.3a' ,结果是'1.2.3a > 1.10.3a,原因是'2'>'10'。

这就要提到js字符串大小的比较。
学习地址-小议 js 下字符串比较大小

字符串大小比较的原理是:按每个字符的 charCode 大小逐个进行比较,直到分出大小为止。
所以,对比'2'>'10'时, 1 charCode 是 49,2 是 50,所以才导致这个结果

还有些容错没有想到,这里就不提了,下面是百度的大神答案,测试发现在比较时,跟我有相同的问题,就是字符串比较

let version1 = 'v1.2.97a';
let version2 = 'v1.10.1b';
let versionArr1 = version1.replace(/[a-zA-Z]/g, (match,i)=> '.' + match.charCodeAt()).split(/[^\d]/);
let versionArr2 = version2.replace(/[a-zA-Z]/g, (match,i)=> '.' + match.charCodeAt()).split(/[^\d]/);

// 保证两个数据长度一样,面向 `v1.2` 和 `v1.2.3` 这样的情况
if(versionArr1.length > versionArr2.length) {
    versionArr2.splice(versionArr2.length, 0, ...Array(versionArr1.length-versionArr2.length).fill(0))
} else {
    versionArr1.splice(versionArr1.length, 0, ...Array(versionArr2.length-versionArr1.length).fill(0))
}

// 按节比较
let result = 'version1 equels version2.'
for(let i=0 ; i < versionArr1.length; i ++) {
    if (versionArr1[i] > versionArr2[i]) {
        result = 'version1 is bigger.';
        break;
    } else if (versionArr1[i] < versionArr2[i]){
        result = 'version2 is bigger.';
        break;
    } 
}
console.log(result);
//version1 is bigger.
复制代码

我觉得,这里可以改的地方是,要么转换类型,要么字符串拼接时用0补位,让对比的数字位数相等

下面字符串用0补位的大神代码,学习地址—js比较版本号

//假定字符串的每节数都在5位以下
function toNum(a){
    var a=a.toString();
    //也可以这样写 var c=a.split(/\./);
    var c=a.split('.');
    var num_place=["","0","00","000","0000"],r=num_place.reverse();
    for (var i=0;i<c.length;i++){ 
        var len=c[i].length;       
        c[i]=r[len]+c[i];  
    } 
    var res= c.join(''); 
    return res; 
} 
function cpr_version(a,b){ 
    var _a=toNum(a),_b=toNum(b);   
    if(_a==_b) console.log("版本号相同!版本号为:"+a);    
    if(_a>_b) console.log("版本号"+a+"是新版本!"); 
    if(_a<_b) console.log("版本号"+b+"是新版本!"); 
}
var a="2.2.3";b="2.1.15";    
cpr_version(a,b);
复制代码

从开始学习前端,到实习,到正式进入工作。有很多知识点是不经常用的(跟我的工作内容相关),但是却很重要,这可能是其他公司经常需要面对的问题。

作为一个想要成为前端工程师的我,必然不能局限在工作环境下。 保证每天学习,复习,哪怕只是一点点,日积月累的知识终会大的可怕。

从码农进阶成工程师的路还长着呢。

我是个不喜欢学习的人,但还要时刻提醒自己学习,哪怕努力的原因,仅仅是不想被别人落下