专栏名称: SegmentFault思否
SegmentFault (www.sf.gg)开发者社区,是中国年轻开发者喜爱的极客社区,我们为开发者提供最纯粹的技术交流和分享平台。
目录
相关文章推荐
程序员的那些事  ·  清华大学:DeepSeek + ... ·  3 天前  
程序员的那些事  ·  印度把 DeepSeek ... ·  3 天前  
程序员小灰  ·  3个令人惊艳的DeepSeek项目,诞生了! ·  2 天前  
程序猿  ·  “我真的受够了Ubuntu!” ·  4 天前  
程序员的那些事  ·  成人玩偶 + ... ·  5 天前  
51好读  ›  专栏  ›  SegmentFault思否

JavaScript 打怪升级 -- 把业务逻辑当练习题做

SegmentFault思否  · 公众号  · 程序员  · 2017-12-21 12:00

正文

1.前言

开发项目和出没社区有一段时间了,会遇上一些比较有印象业务需求。这些业务需求,可能是自己开发项目遇上的,可能是在社区看到的业务需求,或者其他情况接触到的需求,但是这些业务需求的实现逻辑都值得一写。因为这些业务逻辑可以当做练习题一样,可以给大家练手。也希望大家从这些需求实现的逻辑里面可以能到javascript的相关知识,当然如果大家觉得代码需要怎样优化,或者有什么建议,更好的实现方案,觉得我哪里写错了,或者有觉得可以分享的需求,可以在评论提下!

2.月份坐标轴

这个需求是,看下图就懂了

实现方式其实很简单,我在代码打上注释,大家就懂了!

  1.    var _date=[],dateData=["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"];

  2.    //准备一个月份反转的数组

  3.    var dateDataRet=Object.assign([],dateData).reverse();

  4.    //获取当前年份

  5.    var yearText=new Date().getFullYear();

  6.    //获取当前月份  调试的时候,大家可以通过调整now调试  3月-now=2,12月now=11...

  7.    var now=new Date().getMonth();

  8.    for(let i=0;i<6;i++){

  9.        if(now-i<0){

  10.            //如果now-i<0,从dateDataRet里面拿数据,下标=|now-i|-1。

  11.            _date.push(yearText-1+'年' +dateDataRet[Math.abs(now-i)-1]);

  12.        }

  13.        else{

  14.            //从dateData里面拿数据,下标=now-i

  15.            _date.push(yearText+'年'+dateData[now-i]);

  16.        }

  17.    }

  18.    _date.reverse();

可能大家看着会懵,直接看下面的循环图就懂了

3.数值区间

如下图,就是几个数值区间,而且会有一个最小值和最大值

  1.    var _min=5,_max=50;

  2.    function checkArr(arr,min,max){

  3.        //排序

  4.        arr.sort(function(n1,n2){return n1.min-n2.min})

  5.        //遍历

  6.        for(var i=0;i

  7.            //区间的最小值不能大于等于区间最大值

  8.            if(arr[i].min>=arr[i].max){

  9.                console.log('区间的最小值不能大于等于区间最大值');

  10.                return;

  11.            }

  12.            //区间的最小值不能小于默认最小值

  13.            if(arr[i].min

  14.                console.log('区间的最小值不能小于默认最小值');

  15.                return;

  16.            }

  17.            //区间的最大值不能大于默认最大值

  18.            if(arr[i].max>max){

  19.                console.log('区间的最大值不能大于默认最大值');

  20.                return;

  21.            }

  22.            //元素对比,从第二个元素开始

  23.            if(i>0){

  24.                //minInclude,maxInclude,为false就是不包含,为true就是包含

  25.                //{min:10,max:20,minInclude:false,maxInclude:false}

  26.                //等同于(10,20)

  27.                //{min:20,max:30,minInclude:true,maxInclude:false}

  28.                //等同于[20,30);

  29.                //如果前一个的最大值和当前的最小值都是包含情况,那么当前区间的最小值一定要比前一个区间的最大值大1

  30.                if(arr[i].minInclude&&arr[i-1].maxInclude&&arr[i].min-arr[i-1].max!==1){

  31.                    console.log('取值范围错误-当前区间的最小值和前一个区间的最大值都是包含情况,当前区间的最小值一定要比前一个区间的最大值大1');

  32.                       return;

  33.                }

  34.                //如果前一个的最大值和当前的最小值。一个是包含,一个是不包含,那么当前区间的的最小值一定要等于上一个区间的最大值

  35.                else if(arr[i].minInclude!==arr[i-1].maxInclude&&arr[i].min!==arr[i-1].max){

  36.                    console.log('取值范围错误-当前区间的最小值和前一个区间的最大值其中一个是包含,一个是不包含情况,当前区间的最小值一定要等于前一个区间的最大值');

  37.                    return;

  38.                }

  39.                //如果前一个的最大值和当前的最小值都是不包含,肯定不满足

  40.                else if((!arr[i].minInclude)&&(!arr[i-1].maxInclude)){

  41.                    console.log('取值范围错误-前一个的最大值和当前的最小值都是不包含情况,不满足收尾相连');

  42.                    return;

  43.                }

  44.            }

  45.        }

  46.    }

测试用例

  1.    var arr1=[{min:10,max:20,minInclude:false,maxInclude:true },{min:21,max:30,minInclude:true,maxInclude:true}],

  2.    arr2=[{min:10,max:20,minInclude:false,maxInclude:true},{min:20,max:30,minInclude:true,maxInclude:false}],

  3.    arr3=[{min:10,max:20,minInclude:false,maxInclude:true},{min:20,max:30,minInclude:false,maxInclude:false}],

  4.    arr4=[{min:10,max:20,minInclude:false,maxInclude:false},{min:20,max:30,minInclude:true,maxInclude:false}],

  5.    arr5=[{min:10,max:20,minInclude:false,maxInclude:false},{min:21,max:30,minInclude:true,maxInclude:false}],

  6.    arr6=[{min:10,max:20,minInclude:false,maxInclude:false},{min:15,max:30,minInclude:false,maxInclude:false}],

  7.    arr7=[{min:10,max:20 ,minInclude:false,maxInclude:false},{min:20,max:30,minInclude:false,maxInclude:false}],

  8.    arr8=[{min:1,max:20,minInclude:false,maxInclude:false},{min:20,max:30,minInclude:false,maxInclude:false}],

  9.    arr9=[{min:20,max:20,minInclude:false,maxInclude:false},{min:20,max:30,minInclude:false,maxInclude:false}],

  10.    arr10=[{min:20,max:30,minInclude:false,maxInclude:false},{min:20,max:70,minInclude:false,maxInclude:false}];  

运行结果

4.数组对比

这个基于我回答过的一个问题,现在化用,改写一下

JavaScript如何对比两个数组?数组B根据数组A来做出增删? (不用jquery,原生js)

具体问题是这样的:

arryA

  1.    var arrayA = ['a','b','c'];

arryB

  1.    var arrayB = [{

  2.        key: 'a',

  3.        num1:'1',

  4.        num2:'2',

  5.        num3:'3',

  6.        tot:'6'

  7.    },{

  8.        key:'b',

  9.        num1:'11',

  10.        num2:'22',

  11.        num3:'33',

  12.        tot:'66'

  13.    },{

  14.        key: 'c',

  15.        num1: '111',

  16.        num2: '222',

  17.        num3: '333',

  18.        tot:666

  19.    }];

1、如果arryA中有a,arryB中没有,那么在arryB中增加一个key值为a的boj,且其他属性值可均为'0';如下: {key:'a',num1:'0',num2:'0',num3:'0',tot':0'}

2、如果arryA中有a,arryB中也有key值为a的obj,那么arryB则不改变,并且该obj里的其他属性和属性值均不变;

3、如果在arryA中删除了a,那么arryB中key值为a的obj整个删掉。

  1.    //准备临时数组

  2.    function compareArr(arr1,arr2){

  3.        var result=[],arr;

  4.         //遍历

  5.        for(var i=0;i

  6.            //根据arr1[i]的值,查找arrayB,如果arr2中的有满足条件(arrayB中的对象,有key值等于arrayA[i])的项,就会返回满足条件的项,否则返回underfind;

  7.            arr=arr2.find(function(val){return val.key===arr1[i]});

  8.            //如果arr不是undefind,就会添加arr,否则添加{key:arrayA[i],num1:'0',num2:'0',num3:'0',tot:'0'}。

  9.            arr?result.push(arr):result.push({key:arrayA[i],num1:'0',num2:'0',num3:'0',tot:'0'});

  10.        }

  11.    }

测试

  1.    var arrayA = ['b','c'];

  2.    var arrayB = [{

  3.        key:'a',

  4.        num1:'1',

  5.        num2:'2',

  6.        num3:'3',

  7.        tot:'6'

  8.    },{

  9.        key:'b',

  10.        num1: '11',

  11.        num2:'22',

  12.        num3:'33',

  13.        tot:'66'

  14.    },{

  15.        key: 'c',

  16.        num1: '111',

  17.        num2: '222',

  18.        num3: '333',

  19.        tot:666

  20.    }];

  21.    compareArr(arrayA,arrayB);

5.学院获奖

统计学生申请优秀毕业生,并且符合条件的(成绩优秀,拿过奖学金,获得过三好学生)。前提是要申请

大概的流程图就是像下面这样!

我在代码上写上注释,相信不难理解了

  1.    //学生列表

  2.    //isApply:是否有申请优秀毕业生

  3.    let studentList = [

  4.        {

  5.            name: 'aa',

  6.            isApply: false,

  7.            id: 1

  8.        },

  9.        {

  10.            name: 'bb',

  11.            isApply: true,

  12.            id: 2

  13.        },

  14.        {

  15.            name: 'cc',

  16.            isApply: true,

  17.            id: 3

  18.        }

  19.    ];

  20.    //申请优秀毕业生的学生 isApply:true

  21.    let _student = studentList.filter(function (item) {

  22.        return item.isApply;

  23.    });

  24.    //isExcellent:优秀学生的id列表

  25.    //isScholarship:获得过奖学金的学生的id列表

  26.    //isThreeGood:获得过三好学生的学生的id列表

  27.    //accord:集合

  28.    let isExcellent = [1, 2, 3, 4, 5], isScholarship = [4, 2, 5, 6 , 2, 1, 2], isThreeGood = [2, 1, 4, 52, 36], accord = [];

  29.    //数组去重函数

  30.    function removeRepeatArr(arr) {

  31.        return arr.filter(function (item, index, self) {

  32.            return self.indexOf(item) === index;

  33.        });

  34.    }

  35.    //统计数组中,一个遇上元素的出现次数

  36.    function getEleCount(obj, ele) {

  37.        let num = 0;

  38.        for (let i = 0, len = obj.length; i < len; i++) {

  39.            if (ele === obj[i]) {

  40.                num++;

  41.            }

  42.        }

  43.        return num;

  44.    }

  45.     //添加学生记录,把获得成绩优秀的学生的id,获得过奖学金的学生的id,获得过三好学生的id添加进去。

  46.    //但是添加之前,要对获得成绩优秀的学生的id,获得过奖学金的学生的id,获得过三好学生的id。这个三个数组进行去重再添加进accord,因为一个学生可能不止一次成绩优秀,不止一次获得过奖学金,不止一次获得过三好学生

  47.    //这样就方便下面的判断,只要学生的id在accord里面出现两次及以上就符合条件

  48.    accord.push.apply(accord, removeRepeatArr(isExcellent));

  49.    accord.push.apply(accord, removeRepeatArr(isScholarship));

  50.    accord.push.apply(accord, removeRepeatArr(isThreeGood));

  51.    console.log(accord);

  52.    //符合条件的学生列表

  53.    let accordStudent = [];

  54.    for (let i = 0; i < _student.length; i++) {

  55.        //只要学生的id在accord里面出现两次及以上

  56.        if (getEleCount(accord, _student[i].id) >= 2) {

  57.            //记录哪些学生符合条件

  58.            accordStudent.push(_student[i]);

  59.        }

  60.    }

  61.    console.log(accordStudent);

6.数组连续的最大长度

这个也是出于我回答过的问题:如下

  1.    //假如有一个数组,下面这个数组最大的连续长度就是4——————8,9,10,11

  2.    var arr=[1,2,4,5,6,8,9,10,11];

  3.    //代码实现

  4.    function countLen(arr){

  5.        //如果参数不是数组或者长度为0,直接返回0

  6.        if(arr.constructor!==Array||arr.length===0){return 0;}

  7.        //首先进入当前连续长度nowLen设初始化为1,最大连续长度maxLen初始化为0

  8.        var nowLen=1,maxLen=0;

  9.        for(var i=1,len=arr.length;i

  10.            //当前数组元素是不是比上一个数组大1

  11.            if(arr[i]-arr[i-1]===1){

  12.                //如果是,当前连续长度nowLen+1    

  13.                nowLen++;

  14.            }

  15.            else{

  16.                //否则先判断,当前连续长度是否大于最大连续长度

  17.                if(maxLen

  18.                    //如果是就赋值

  19.                    maxLen=nowLen

  20.                }

  21.                //当前连续长度初始化为1

  22.                nowLen=1;

  23.            }

  24.        }

  25.        //循环完再判断一次当前连续长度是否大于最大连续长度(避免最大连续长度是数组最后面几个数组时产生的bug)

  26.        if(maxLen

  27.            maxLen=nowLen

  28.        }

  29.        //返回最大连续长度

  30.        return maxLen;

  31.    }

7.答题连对数

这个和上面的代码基本一样,只是判断条件毫厘之差,直接贴,大家看就好

  1.    function countTrue(arr){debugger;

  2.        //如果参数不是数组或者长度为0,直接返回0

  3.        if(arr.constructor!==Array||arr.length===0){return 0;}

  4.        //首先初始化连续答对长度nowLen为0,最大连续答对长度maxLen为0

  5.        var nowLen=0,maxLen=0;

  6.        for(var i=0,len=arr.length;i

  7.            //当前数组元素是不是比上一个数组大1

  8.            if(arr[i]){

  9.                //如果是,当前连续长度nowLen+1

  10.                nowLen++;

  11.            }

  12.            else{

  13.                //否则先判断,当前连续长度是否大于最大连续长度

  14.                if(maxLen

  15.                    //如果是就赋值

  16.                    maxLen=nowLen

  17.                }

  18.                //当前连续长度初始化为0

  19.                nowLen=0;

  20.            }

  21.        }

  22.        //循环完再判断一次当前连续长度是否大于最大连续长度(避免最大连续长度是数组最后面几个数组时产生的bug)

  23.        if(maxLen

  24.            maxLen=nowLen

  25.        }

  26.        //返回最大连续长度

  27.        return maxLen;

  28.    }

8.命名方式转换

比如驼峰命名方式转'-'命名方式。

  1.    var str = "shouHou";

  2.     //$1-第一个括号匹配的内容

  3.    //这个实例,$1='H'

  4.    str = str.replace(/([A-Z])/g,"-$1").toLowerCase();

比如'-'命名方式转驼峰命名方式

  1.    var str="shou-hou";

  2.    //$0-匹配的结果   $1-第一个括号匹配的内容

  3.    //这个实例$0='-h'    $1='h'

  4.    str=str.replace(/-(\w)/g,function($0,$1){

  5.        return $1.toUpperCase();

  6.    });

9.格式化字符

这个最常见的就是在金额方面的显示需求上,比如后台返回10000。前端要显示成10,000或者其他格式等!

  1.    //str

  2.    //size-每隔几个字符进行分割 默认3

  3.    //delimiter-分割符 默认','

  4.    function formatText(str,size,delimiter){

  5.        var _str=str.toString();

  6.        var _size=size||3,_delimiter=delimiter||',';

  7.        /*

  8.         如果_size是3

  9.         "\d{1,3}(?=(\d{3})+$)"

  10.         */

  11.         var regText='\\d{1,'+_size+'}(?=(\\d{'+_size+'})+$)';

  12.        /*  

  13.        /\d{1,3}(?=(\d{3})+$)/g     这个正则的意思:匹配连续的三个数字,但是这些三个数字不能是字符串的开头1-3个字符  

  14.         */

  15.        var reg=new RegExp(regText,'g');

  16.        /*

  17.        (-?) 匹配前面的-号   (\d+)匹配中间的数字   ((\.\d+)?)匹配小数点后面的数字

  18.        //$0-匹配结果,$1-第一个括号返回的内容----(-?)    $2,$3如此类推  

  19.        */

  20.        return _str.replace(/^(-?)(\d+)((\.\d+)?)$/, function ($0, $1, $2, $3) {

  21.              return $1 + $2.replace(reg, '$&,') + $3;

  22.        })

  23.    }

10.对象合并,并且记录异常数据

这个需求,可能大家有点懵。下面实例分析 比如有两个都地方记录了我的信息

  1.    let info1={

  2.            name:"守候",

  3.            sex:"男",

  4.            age:24,

  5.            job:"web前端"

  6.        },info2={

  7.            name:"守候!",

  8.            country:"china",

  9.            interest:"basketball",

  10.            phone:"12345678910",

  11.            job:"web前端"

  12.        }

现在要合并我的信息,并且记录可能有异常的信息。比如上面的name属性,在两个对象都有,而且两个对象的值不一样,那么就不知道到底是info1中的name属性是正确的,还是info2中的name属性是正确的。所以,就得把name这个属性记录起来,方便以后核对name这个属性。

如下图







请到「今天看啥」查看全文