JavaScript 打怪升級 —— 把業務邏輯當練習題做

發表於2017-12-21

1.前言

開發專案和出沒社群有一段時間了,會遇上一些比較有印象業務需求。這些業務需求,可能是自己開發專案遇上的,可能是在社群看到的業務需求,或者其他情況接觸到的需求,但是這些業務需求的實現邏輯都值得一寫。因為這些業務邏輯可以當做練習題一樣,可以給大家練手。也希望大家從這些需求實現的邏輯裡面可以能到javascript的相關知識,當然如果大家覺得程式碼需要怎樣優化,或者有什麼建議,更好的實現方案,覺得我哪裡寫錯了,或者有覺得可以分享的需求,可以在評論提下!

2.月份座標軸

這個需求是,看下圖就懂了

JavaScript 打怪升級 —— 把業務邏輯當練習題做

JavaScript 打怪升級 —— 把業務邏輯當練習題做

實現方式其實很簡單,我在程式碼打上註釋,大家就懂了!

var _date=[],dateData=["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"];
//準備一個月份反轉的陣列
var dateDataRet=Object.assign([],dateData).reverse();
//獲取當前年份
var yearText=new Date().getFullYear();
//獲取當前月份  除錯的時候,大家可以通過調整now除錯  3月-now=2,12月now=11...
var now=new Date().getMonth();
for(let i=0;i<6;i++){
    if(now-i<0){
        //如果now-i<0,從dateDataRet裡面拿資料,下標=|now-i|-1。
        _date.push(yearText-1+'年'+dateDataRet[Math.abs(now-i)-1]);
    }
    else{
        //從dateData裡面拿資料,下標=now-i
        _date.push(yearText+'年'+dateData[now-i]);
    }

}
_date.reverse();複製程式碼

可能大家看著會懵,直接看下面的迴圈圖就懂了

JavaScript 打怪升級 —— 把業務邏輯當練習題做

3.數值區間

如下圖,就是幾個數值區間,而且會有一個最小值和最大值

JavaScript 打怪升級 —— 把業務邏輯當練習題做

var _min=5,_max=50;
function checkArr(arr,min,max){
    //排序
    arr.sort(function(n1,n2){return n1.min-n2.min})
    //遍歷
    for(var i=0;i<arr.length;i++){
        //區間的最小值不能大於等於區間最大值
        if(arr[i].min>=arr[i].max){
            console.log('區間的最小值不能大於等於區間最大值');
            return;
        }
        //區間的最小值不能小於預設最小值
        if(arr[i].min<min){
            console.log('區間的最小值不能小於預設最小值');
            return;
        }
                    
        //區間的最大值不能大於預設最大值
        if(arr[i].max>max){
            console.log('區間的最大值不能大於預設最大值');
            return;
        }
        //元素對比,從第二個元素開始
        if(i>0){
            //minInclude,maxInclude,為false就是不包含,為true就是包含
            //{min:10,max:20,minInclude:false,maxInclude:false}
            //等同於(10,20)
            //{min:20,max:30,minInclude:true,maxInclude:false}
            //等同於[20,30);
            
            //如果前一個的最大值和當前的最小值都是包含情況,那麼當前區間的最小值一定要比前一個區間的最大值大1
            if(arr[i].minInclude&&arr[i-1].maxInclude&&arr[i].min-arr[i-1].max!==1){
                console.log('取值範圍錯誤-當前區間的最小值和前一個區間的最大值都是包含情況,當前區間的最小值一定要比前一個區間的最大值大1');
                   return;
                
            }
            //如果前一個的最大值和當前的最小值。一個是包含,一個是不包含,那麼當前區間的的最小值一定要等於上一個區間的最大值
            else if(arr[i].minInclude!==arr[i-1].maxInclude&&arr[i].min!==arr[i-1].max){
                console.log('取值範圍錯誤-當前區間的最小值和前一個區間的最大值其中一個是包含,一個是不包含情況,當前區間的最小值一定要等於前一個區間的最大值');
                return;
            }
            //如果前一個的最大值和當前的最小值都是不包含,肯定不滿足
            else if((!arr[i].minInclude)&&(!arr[i-1].maxInclude)){
                console.log('取值範圍錯誤-前一個的最大值和當前的最小值都是不包含情況,不滿足收尾相連');
                return;
            }
        }
    }
}

複製程式碼

測試用例

var arr1=[{min:10,max:20,minInclude:false,maxInclude:true},{min:21,max:30,minInclude:true,maxInclude:true}],
arr2=[{min:10,max:20,minInclude:false,maxInclude:true},{min:20,max:30,minInclude:true,maxInclude:false}],
arr3=[{min:10,max:20,minInclude:false,maxInclude:true},{min:20,max:30,minInclude:false,maxInclude:false}],
arr4=[{min:10,max:20,minInclude:false,maxInclude:false},{min:20,max:30,minInclude:true,maxInclude:false}],
arr5=[{min:10,max:20,minInclude:false,maxInclude:false},{min:21,max:30,minInclude:true,maxInclude:false}],
arr6=[{min:10,max:20,minInclude:false,maxInclude:false},{min:15,max:30,minInclude:false,maxInclude:false}],
arr7=[{min:10,max:20,minInclude:false,maxInclude:false},{min:20,max:30,minInclude:false,maxInclude:false}],
arr8=[{min:1,max:20,minInclude:false,maxInclude:false},{min:20,max:30,minInclude:false,maxInclude:false}],
arr9=[{min:20,max:20,minInclude:false,maxInclude:false},{min:20,max:30,minInclude:false,maxInclude:false}], 
arr10=[{min:20,max:30,minInclude:false,maxInclude:false},{min:20,max:70,minInclude:false,maxInclude:false}];  
複製程式碼

執行結果

JavaScript 打怪升級 —— 把業務邏輯當練習題做

4.陣列對比

這個基於我回答過的一個問題,現在化用,改寫一下

JavaScript如何對比兩個陣列?陣列B根據陣列A來做出增刪? (不用jquery,原生js)
具體問題是這樣的:

arryA

var arrayA = ['a','b','c'];
複製程式碼

arryB

var arrayB = [{
    key:'a',
    num1:'1',
    num2:'2',
    num3:'3',
    tot:'6'
},{
    key:'b',
    num1:'11',
    num2:'22',
    num3:'33',
    tot:'66'
},{
    key: 'c',
    num1: '111',
    num2: '222',
    num3: '333',
    tot:666
}];
複製程式碼

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整個刪掉。

//準備臨時陣列
function compareArr(arr1,arr2){
    var result=[],arr;
    //遍歷
    for(var i=0;i<arr1.length;i++){
        //根據arr1[i]的值,查詢arrayB,如果arr2中的有滿足條件(arrayB中的物件,有key值等於arrayA[i])的項,就會返回滿足條件的項,否則返回underfind;
        arr=arr2.find(function(val){return val.key===arr1[i]});
        //如果arr不是undefind,就會新增arr,否則新增{key:arrayA[i],num1:'0',num2:'0',num3:'0',tot:'0'}。
        arr?result.push(arr):result.push({key:arrayA[i],num1:'0',num2:'0',num3:'0',tot:'0'});
    }
}

複製程式碼

測試

var arrayA = ['b','c'];
var arrayB = [{
    key:'a',
    num1:'1',
    num2:'2',
    num3:'3',
    tot:'6'
},{
    key:'b',
    num1:'11',
    num2:'22',
    num3:'33',
    tot:'66'
},{
    key: 'c',
    num1: '111',
    num2: '222',
    num3: '333',
    tot:666
}];
compareArr(arrayA,arrayB);
複製程式碼

JavaScript 打怪升級 —— 把業務邏輯當練習題做

5.學院獲獎

統計學生申請優秀畢業生,並且符合條件的(成績優秀,拿過獎學金,獲得過三好學生)。前提是要申請

大概的流程圖就是像下面這樣!

JavaScript 打怪升級 —— 把業務邏輯當練習題做

我在程式碼上寫上註釋,相信不難理解了

//學生列表
//isApply:是否有申請優秀畢業生
let studentList = [
    {
        name: 'aa',
        isApply: false,
        id: 1
    },
    {
        name: 'bb',
        isApply: true,
        id: 2
    },
    {
        name: 'cc',
        isApply: true,
        id: 3
    }
];

//申請優秀畢業生的學生 isApply:true

let _student = studentList.filter(function (item) {
    return item.isApply;
});
//isExcellent:優秀學生的id列表
//isScholarship:獲得過獎學金的學生的id列表
//isThreeGood:獲得過三好學生的學生的id列表
//accord:集合
let isExcellent = [1, 2, 3, 4, 5], isScholarship = [4, 2, 5, 6, 2, 1, 2], isThreeGood = [2, 1, 4, 52, 36], accord = [];
//陣列去重函式
function removeRepeatArr(arr) {
    return arr.filter(function (item, index, self) {
        return self.indexOf(item) === index;
    });
}

//統計陣列中,一個遇上元素的出現次數
function getEleCount(obj, ele) {
    let num = 0;
    for (let i = 0, len = obj.length; i < len; i++) {
        if (ele === obj[i]) {
            num++;
        }
    }
    return num;
}

//新增學生記錄,把獲得成績優秀的學生的id,獲得過獎學金的學生的id,獲得過三好學生的id新增進去。
//但是新增之前,要對獲得成績優秀的學生的id,獲得過獎學金的學生的id,獲得過三好學生的id。這個三個陣列進行去重再新增進accord,因為一個學生可能不止一次成績優秀,不止一次獲得過獎學金,不止一次獲得過三好學生
//這樣就方便下面的判斷,只要學生的id在accord裡面出現兩次及以上就符合條件
accord.push.apply(accord, removeRepeatArr(isExcellent));
accord.push.apply(accord, removeRepeatArr(isScholarship));
accord.push.apply(accord, removeRepeatArr(isThreeGood));
console.log(accord);
//符合條件的學生列表
let accordStudent = [];
for (let i = 0; i < _student.length; i++) {
    //只要學生的id在accord裡面出現兩次及以上
    if (getEleCount(accord, _student[i].id) >= 2) {
        //記錄哪些學生符合條件
        accordStudent.push(_student[i]);
    }
}
console.log(accordStudent);
複製程式碼

6.陣列連續的最大長度

這個也是出於我回答過的問題:如下

//假如有一個陣列,下面這個陣列最大的連續長度就是4——————8,9,10,11
var arr=[1,2,4,5,6,8,9,10,11];

//程式碼實現
function countLen(arr){
    //如果引數不是陣列或者長度為0,直接返回0
    if(arr.constructor!==Array||arr.length===0){return 0;}
    //首先進入當前連續長度nowLen設初始化為1,最大連續長度maxLen初始化為0
    var nowLen=1,maxLen=0;
    
    for(var i=1,len=arr.length;i<len;i++){
        //當前陣列元素是不是比上一個陣列大1
        if(arr[i]-arr[i-1]===1){
            //如果是,當前連續長度nowLen+1    
            nowLen++;
        }
        else{
            //否則先判斷,當前連續長度是否大於最大連續長度
            if(maxLen<nowLen){
                //如果是就賦值
                maxLen=nowLen
            }
            //當前連續長度初始化為1
            nowLen=1;
        }
    }
    //迴圈完再判斷一次當前連續長度是否大於最大連續長度(避免最大連續長度是陣列最後面幾個陣列時產生的bug)
    if(maxLen<nowLen){
        maxLen=nowLen
    }
    //返回最大連續長度
    return maxLen;
}
複製程式碼

JavaScript 打怪升級 —— 把業務邏輯當練習題做

JavaScript 打怪升級 —— 把業務邏輯當練習題做

7.答題連對數

這個和上面的程式碼基本一樣,只是判斷條件毫釐之差,直接貼,大家看就好

function countTrue(arr){debugger;
    //如果引數不是陣列或者長度為0,直接返回0
    if(arr.constructor!==Array||arr.length===0){return 0;}
    //首先初始化連續答對長度nowLen為0,最大連續答對長度maxLen為0
    var nowLen=0,maxLen=0;
    for(var i=0,len=arr.length;i<len;i++){
        //當前陣列元素是不是比上一個陣列大1
        if(arr[i]){
            //如果是,當前連續長度nowLen+1
            nowLen++;
        }
        else{
            //否則先判斷,當前連續長度是否大於最大連續長度
            if(maxLen<nowLen){
                //如果是就賦值
                maxLen=nowLen
            }
            //當前連續長度初始化為0
            nowLen=0;
        }
    }
    //迴圈完再判斷一次當前連續長度是否大於最大連續長度(避免最大連續長度是陣列最後面幾個陣列時產生的bug)
    if(maxLen<nowLen){
        maxLen=nowLen
    }
    //返回最大連續長度
    return maxLen;
}
複製程式碼

JavaScript 打怪升級 —— 把業務邏輯當練習題做

8.命名方式轉換

比如駝峰命名方式轉'-'命名方式。

var str = "shouHou";
//$1-第一個括號匹配的內容
//這個例項,$1='H'
str = str.replace(/([A-Z])/g,"-$1").toLowerCase();
複製程式碼

JavaScript 打怪升級 —— 把業務邏輯當練習題做

比如'-'命名方式轉駝峰命名方式

var str="shou-hou";
//$0-匹配的結果   $1-第一個括號匹配的內容
//這個例項$0='-h'    $1='h'
str=str.replace(/-(\w)/g,function($0,$1){
    return $1.toUpperCase();
}); 
複製程式碼

JavaScript 打怪升級 —— 把業務邏輯當練習題做

9.格式化字元

這個最常見的就是在金額方面的顯示需求上,比如後臺返回10000。前端要顯示成10,000或者其他格式等!

//str
//size-每隔幾個字元進行分割 預設3
//delimiter-分割符 預設','
function formatText(str,size,delimiter){
    var _str=str.toString();
    var _size=size||3,_delimiter=delimiter||',';
    /* 
     如果_size是3
     "\d{1,3}(?=(\d{3})+$)" 
     */
    var regText='\\d{1,'+_size+'}(?=(\\d{'+_size+'})+$)';
    /*   
    /\d{1,3}(?=(\d{3})+$)/g     這個正則的意思:匹配連續的三個數字,但是這些三個數字不能是字串的開頭1-3個字元  
     */
    var reg=new RegExp(regText,'g');
    /* 
    (-?) 匹配前面的-號   (\d+)匹配中間的數字   ((\.\d+)?)匹配小數點後面的數字
    //$0-匹配結果,$1-第一個括號返回的內容----(-?)    $2,$3如此類推  
    */
    return _str.replace(/^(-?)(\d+)((\.\d+)?)$/, function ($0, $1, $2, $3) {
          return $1 + $2.replace(reg, '$&,') + $3;
    })
}

複製程式碼

JavaScript 打怪升級 —— 把業務邏輯當練習題做

10.物件合併,並且記錄異常資料

這個需求,可能大家有點懵。下面例項分析
比如有兩個都地方記錄了我的資訊

let info1={
        name:"守候",
        sex:"男",
        age:24,
        job:"web前端"
    },info2={
        name:"守候!",
        country:"china",
        interest:"basketball",
        phone:"12345678910",
        job:"web前端"
    }複製程式碼

現在要合併我的資訊,並且記錄可能有異常的資訊。比如上面的name屬性,在兩個物件都有,而且兩個物件的值不一樣,那麼就不知道到底是info1中的name屬性是正確的,還是info2中的name屬性是正確的。所以,就得把name這個屬性記錄起來,方便以後核對name這個屬性。

如下圖

JavaScript 打怪升級 —— 把業務邏輯當練習題做

下面,一步一步來,先不管3721,直接合並屬性

let objAll={};
function assignObj(objArr) {
    let _obj={};
    for(let i=0;i<objArr.length;i++){
        _obj=Object.assign(_obj,objArr[i],{});
    }
    return JSON.parse(JSON.stringify(_obj));
}
objAll=assignObj([objA,objB]); 複製程式碼

然後先準備一個欄位,記錄哪些異常資訊

objAll.warnInfo=[];複製程式碼

最後檢查物件,判斷哪些資訊有異常

  function checkObj(_objAll,objList) {
        //獲取所有屬性
        let _keys=Object.keys(_objAll);
        for(let i=0;i<objList.length;i++){
            for(let j=0;j<_keys.length;j++){
                //如果_keys[j]這個屬性,在objList[i]和_objAll裡面都存在,而且這兩個值是不一樣的,那麼就是一場資料,需要記錄!
                if(objList[i][_keys[j]]!==undefined&&_objAll[_keys[j]]!==objList[i][_keys[j]]){
                    _objAll.isError.push(_keys[j]);
                }
            }
        }
        return _objAll;
    }
    console.log(checkObj(objAll,[objA,objB]));  
     
複製程式碼

11.篩選標籤

如下圖,在下面渲染這個標籤

JavaScript 打怪升級 —— 把業務邏輯當練習題做

大家可能第一可能覺得壓根沒難度
就是一個物件陣列:比如

var searchTag=[
    {label:'產品編碼',value:'100072236-8'},
    {label:'產品名稱',value:'甘油'}
]複製程式碼

但是這樣的資料,顯然是要經過處理生成的

因為不可能這樣傳送請求

http://example.com?產品編碼=100072236-8複製程式碼

傳送過去的引數應該是這樣的

http://example.com?proId=100072236-8

var searchParam={proId:'100072236-8',proName:'甘油'}   複製程式碼

怎麼進行資料的處理呢,其實很簡單,程式碼不打註釋,我想都看得懂

var searchTag=[];
var searchText={proId:'產品編碼',proName:'產品名稱'};
var searchParam={proId:'100072236-8',proName:'甘油'};
Object.keys(searchParam).forEach(function (item) {
    searchTag.push({
        label:searchText[item],
        key:item,
        value:searchParam[item]
    })
})
console.log(searchTag)    
複製程式碼

JavaScript 打怪升級 —— 把業務邏輯當練習題做

有了這些資料,渲染到頁面這個就簡單了!

12.匯入excel內容

就是excel上這樣的內容

JavaScript 打怪升級 —— 把業務邏輯當練習題做

轉成下面的資料

JavaScript 打怪升級 —— 把業務邏輯當練習題做

JavaScript 打怪升級 —— 把業務邏輯當練習題做

目錄如下

JavaScript 打怪升級 —— 把業務邏輯當練習題做

下面開始寫程式碼,我們利用node.js來寫

let path = require('path');
//使用ejsexcel讀取excel檔案  npm install ejsexcel --save
let ejsExcel=require('ejsexcel');
let fs=require('fs');
//讀取excel
let exBuf=fs.readFileSync(__dirname+'/resource/userList.xlsx');
let _data=[];
//獲取成功後
ejsExcel.getExcelArr(exBuf).then(exlJson=>{
    //獲取excel資料
    let workBook=exlJson;
    //獲取excel第一張表 sheet1
    let workSheets=workBook[0];
    //匯出js的路徑
    let newfilepath=path.join(__dirname,"/resource/test.js");
    //遍歷第一張表的的每一行資料
    workSheets.forEach((item,index)=>{
        //從第二行開始插入,避免連表頭也插入_data裡面
        if(index>0){
            //往_data插入單元格個值,item[0]相當於excel中的姓名,item[1]就是excel中的聯絡電話
            _data.push({
                name:item[0],
                phone:item[1]
            })
        }
    });
    //寫入js檔案
    fs.writeFileSync(newfilepath, 'let _data='+JSON.stringify(_data)+';export {_data}');
}).catch(error=>{
    //列印獲取失敗資訊
    console.log("讀取錯誤!");
    console.log(error);
});複製程式碼

然後命令列執行該js

$ node importFile.js
複製程式碼

然後就發現多了一個test.js檔案

JavaScript 打怪升級 —— 把業務邏輯當練習題做

excel的資料就這樣匯入成js的一個陣列了,只要引入這個陣列,就可以正常的使用了!

13.隨機迴圈

當時接到的業務是實際顯示客戶的資訊,感覺有點像音樂播放器的隨機迴圈。

要求有兩個:
1.一個提示列表裡面,提示的資訊每隔500ms隨機展示。
2.同一輪迴圈裡面,一個提示資訊只能展示一次。
3.列表的提示資訊全部展示完了,進行下一輪展示。
這個邏輯沒什麼,直接在程式碼打上註釋,我想大家就明白了!

var tipList=['提示1','提示2','提示3','提示4','提示5','提示6','提示7','提示8','提示9'];
var tipListShow=[];
tipListShow=Object.assign([],tipList);
var i=0,timer=null;
function play() {
    //隨機顯示一個,顯示了之後,把這個項從tipListShow中刪除掉,防止在同一輪重複出現!
    console.log(tipListShow.splice(Math.floor(Math.random() * tipListShow.length),1)[0]);
    //當迴圈完了之後,tipListShow的長度就會是0,然後就重新賦值,準備進行下一輪的隨機迴圈
    if(tipListShow.length===0){
        tipListShow=Object.assign([],tipList);
        i=0;
    }
    //如果需要暫停或者停止的,清除這個定時器即可,下次執行就重新這樣建立定時器,執行play();!
    timer=setTimeout(function () {
        play();
    },500);
}
play();
複製程式碼

JavaScript 打怪升級 —— 把業務邏輯當練習題做

14.小結

好了,關於我收集到的一些業務需求邏輯,以及實現的方式,就說到這裡了!接觸到的也無需求邏輯很多,但是值得寫的,可以當做練習題的,就記錄到這裡了。我上面程式碼實現可能會有點粗糙,大家有更好的實現方案,歡迎建議一下。如果大家有什麼可以當做練習題的需求,可以提下。讓大家有多些練習題可以嘗試下,學習下!



-------------------------華麗的分割線--------------------
想了解更多,關注關注我的微信公眾號:守候書閣

JavaScript 打怪升級 —— 把業務邏輯當練習題做


相關文章