牛客网js学习总结

来源:互联网 发布:validateform js 编辑:程序博客网 时间:2024/05/16 17:41

  • 数组
    • 查找数组元素位置
    • 数组求和
    • 移除数组中的元素 返回新数组
    • 移除数组中的元素
    • 添加元素
    • 删除数组最后一个元素
    • 添加元素
    • 删除数组第一个元素
    • 数组合并
    • 添加元素
    • 计数
    • 查找重复元素
    • 求二次方
    • 查找元素位置
  • 函数
    • 定时器计时器
    • 函数传参
    • 函数的上下文
    • 二次封装函数
    • 使用 arguments
  • Number
    • 二进制转换
    • 二进制转换
    • 二进制转换
  • 正则
    • 判断是否包含数字
    • 检查重复字符串
    • 判断是否以元音字母结尾
    • 获取指定字符串
    • 判断是否符合指定格式
    • USD格式

数组

1.查找数组元素位置

找出元素 item 在给定数组 arr 中的位置

indexOf

    function indexOf(arr, item) {      if (Array.prototype.indexOf){          return arr.indexOf(item);      } else {          for (var i = 0; i < arr.length; i++){              if (arr[i] === item){                  return i;              }          }      }           return -1;    }

2.数组求和

计算给定数组 arr 中所有元素的总和

不考虑算法复杂度,用递归做:

    function sum(arr) {        var len = arr.length;        if(len == 0){            return 0;        } else if (len == 1){            return arr[0];        } else {            return arr[0] + sum(arr.slice(1));        }    }

常规循环:

    function sum(arr) {        var s = 0;        for (var i=arr.length-1; i>=0; i--) {            s += arr[i];        }        return s;    }

函数式编程 map-reduce:

    function sum(arr) {        return arr.reduce(function(prev, curr, idx, arr){            return prev + curr;        });    }

forEach遍历:

    function sum(arr) {        var s = 0;        arr.forEach(function(val, idx, arr) {            s += val;        }, 0);        return s;    };

eval:

    function sum(arr) {        return eval(arr.join("+"));    };

3.移除数组中的元素 (返回新数组)

移除数组 arr 中的所有值与 item相等的元素。不要直接修改数组arr,结果返回新的数组

1.splice()

    function remove(arr,item){        var newarr = arr.slice(0);        for(var i=0;i<newarr.length;i++){            if(newarr[i] == item){                newarr.splice(i,1);                i--;            }        }        return newarr;    }

2.push()

    function remove(arr,item){        var newarr = [];        for(var i=0;i<arr.length;i++){            if(arr[i] != item){                newarr.push(arr[i]);            }        }        return newarr;    }    function remove(arr,item){        var newarr = [];        for(var i=0;i<arr.length;i++){            if(arr[i] == item)continue;           newarr.push(arr[i]);        }        return nawarr;    }

3.Arra y.prototype.filter()

    function remove(arr,item){        return arr.filter(function(ele){             return ele != item;        })    }

4.移除数组中的元素

移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回

function removeWithoutCopy(arr, item) {    for(var i=0; i<arr.length; i++)    {        if(item == arr[i])        {            arr.splice(i,1);            i--;        }    }    return arr;}

5.添加元素

在数组 arr 末尾添加元素 item。不要直接修改数组 arr,结果返回新的数组

普通的迭代拷贝

var append = function(arr, item) {    var length = arr.length,        newArr = [];    for (var i = 0; i < length; i++) {        newArr.push(arr[i]);    }    newArr.push(item);    return newArr;};

使用slice浅拷贝+push组合

var append2 = function(arr, item) {    var newArr = arr.slice(0);  // slice(start, end)浅拷贝数组    newArr.push(item);    return newArr;};

concat

var append3 = function(arr, item) {    return arr.concat(item);};

join+split+push组合

function append(arr, item) {    var newArr=arr.join().split(',');    newArr.push(item);    return newArr;}

使用unshift.apply

function append(arr, item) {    var newArr=[item];    [].unshift.apply(newArr, arr);    return newArr;}

6.删除数组最后一个元素

删除数组 arr 最后一个元素。不要直接修改数组 arr,结果返回新的数组

利用slice

function truncate(arr) {    return arr.slice(0,-1);}

利用filter

function truncate(arr) {    return arr.filter(function(v,i,ar) {        return i!==ar.length-1;    });}

利用push.apply+pop

function truncate(arr) {    var newArr=[];    [].push.apply(newArr, arr);    newArr.pop();    return newArr;}

利用join+split+pop 注意!!!:数据类型会变成字符型

function truncate(arr) {    var newArr = arr.join().split(',');    newArr.pop();    return newArr;}

利用concat+pop

function truncate(arr) {    var newArr = arr.concat();    newArr.pop();    return newArr;}

普通的迭代拷贝

function truncate(arr, item) {    var newArr=[];    for(var i=0;i<arr.length-1;i++){        newArr.push(arr[i]);    }    return newArr;}

7.添加元素

在数组 arr 开头添加元素 item。不要直接修改数组 arr,结果返回新的数组

利用concat

function prepend(arr, item) {    return [item].concat(arr);}

使用push.apply

function prepend(arr, item) {    var newArr=[item];    [].push.apply(newArr, arr);    return newArr;}

利用slice+unshift/splice

function prepend(arr, item) {    var newArr=arr.slice(0);    newArr.unshift(item);//newArr.splice(0,0,item);    return newArr;}

使用join+split+unshift/splice组合

function prepend(arr, item) {    var newArr=arr.join().split(',');    newArr.unshift(item);//newArr.splice(0,0,item);    return newArr;}

普通的迭代拷贝

function prepend(arr, item) {    var newArr=[];    for(var i=0;i<arr.length;i++){        newArr.push(arr[i]);    }    newArr.unshift(item);    return newArr;}

8.删除数组第一个元素

删除数组 arr 第一个元素。不要直接修改数组 arr,结果返回新的数组

利用slice

function curtail(arr) {    return arr.slice(1);}

利用filter

function curtail(arr) {    return arr.filter(function(v,i) {        return i!==0;    });}

利用push.apply+shift

function curtail(arr) {    var newArr=[];    [].push.apply(newArr, arr);    newArr.shift();    return newArr;}

利用join+split+shift 注意!!!:数据类型会变成字符型

function curtail(arr) {    var newArr = arr.join().split(',');    newArr.shift();    return newArr;}

//利用concat+shift

function curtail(arr) {    var newArr = arr.concat();    newArr.shift();    return newArr;}

//普通的迭代拷贝

    function curtail(arr) {        var newArr=[];        for(var i=1;i<arr.length;i++){            newArr.push(arr[i]);        }        return newArr;    }

9.数组合并

合并数组 arr1 和数组 arr2。不要直接修改数组 arr,结果返回新的数组

//利用concat

function concat(arr1, arr2) {    return arr1.concat(arr2);}

//利用slice+push.apply

function concat(arr1, arr2) {    var newArr=arr1.slice(0);    [].push.apply(newArr, arr2);    return newArr;}

//利用slice+push

function concat(arr1, arr2) {    var newArr=arr1.slice(0);    for(var i=0;i<arr2.length;i++){        newArr.push(arr2[i]);    }    return newArr;}

//普通的迭代拷贝

function concat(arr1, arr2) {    var newArr=[];    for(var i=0;i<arr1.length;i++){        newArr.push(arr1[i]);    }    for(var j=0;j<arr2.length;j++){        newArr.push(arr2[j]);    }    return newArr;}

10.添加元素

在数组 arr 的 index 处添加元素 item。不要直接修改数组 arr,结果返回新的数组

//利用slice+concat

function insert(arr, item, index) {    return arr.slice(0,index).concat(item,arr.slice(index));}

//利用concat +splice

function insert(arr, item, index) {    var newArr=arr.concat();    newArr.splice(index,0,item);    return newArr;}

//利用slice+splice

function insert(arr, item, index) {    var newArr=arr.slice(0);    newArr.splice(index,0,item);    return newArr;}

//利用push.apply+splice

function insert(arr, item, index) {    var newArr=[];    [].push.apply(newArr, arr);    newArr.splice(index,0,item);    return newArr;}

//普通的迭代拷贝

function insert(arr, item, index) {    var newArr=[];    for(var i=0;i<arr.length;i++){        newArr.push(arr[i]);    }    newArr.splice(index,0,item);    return newArr;}

11.计数

统计数组 arr 中值等于 item 的元素出现的次数

//filter()–>利用指定的函数确定是否在返回的数组中包含某一项

    function count(arr, item) {        var count = arr.filter(function(a) {            return a === item;   //返回true的项组成的数组        });        return count.length;    }

//filter()

function count(arr, item) {    return arr.filter(function(a){        return (a==item);    }).length}

//map()–>对数组中的每一项进行给定函数,返回每次函数条用的结果组成的数组;

function count(arr, item) {    var count = 0;    arr.map(function(a) {        if(a === item) {            count++;        }    });    return count;}

//for循环

function count(arr, item) {    var count = 0;    for(var i=0; i<arr.length; i++) {        if(arr[i] === item) {            count++;        }    }    return count;}

//reduce()–>从数组的第一项开始,逐个遍历到最后;

function count(arr, item) {    var count = arr.reduce(function(prev, curr) {        return curr === item ? prev+1 : prev;    }, 0);    return count;}

//forEach()–>对数组中的每一项运行传入的函数

function count(arr, item) {    var count = 0;    arr.forEach(function(a) {        a === item ? count++ : 0;    });    return count;}

12.查找重复元素

找出数组 arr 中重复出现过的元素

先排序然后再判断。先排序,如果后一个与前一个相等且未保存,则保存。

function duplicates(arr) {    var new_arr = arr.sort();//先把arr排序    var res = [] ;//目标容器    for( var i = 0 ; i < new_arr.length ; i++){        if(new_arr[i] == new_arr[i+1] &&        new_arr[i] !=new_arr[i-1]){//判断是否重复,是否已经放入容器            res.push(new_arr[i]);        }    }return res;

上一个改写,for in循环

function duplicates(arr) {    var a=arr.sort(),b=[];    for(var i in a){        if(a[i]==a[i-1] && b.indexOf(a[i])==-1) b.push(a[i]);     }    return b;}

判断索引位置
如果elem的第一个索引和最后一个的索引不一样,说明这个值重复.
在结果数组中这个值不存在,就把这个值添加进去

function duplicates(arr) { var result = [];    arr.forEach(function(elem){       if(arr.indexOf(elem) !=arr.lastIndexOf(elem) && result.indexOf(elem) == -1){           result.push(elem);       }    });    return result;}

计数排序

function duplicates(arr) {     //声明两个数组,a数组用来存放结果,b数组用来存放arr中每个元素的个数     var a = [],b = [];     //遍历arr,如果以arr中元素为下标的的b元素已存在,则该b元素加1,否则设置为1     for(var i = 0; i < arr.length; i++){         if(!b[arr[i]]){             b[arr[i]] = 1;             continue;         }         b[arr[i]]++;         //b[arr[i]]= b[arr[i]]?b[arr[i]]+1:1;//等同于上面的if语句     }     //遍历b数组,将其中元素值大于1的元素下标存入a数组中     for(var i = 0; i < b.length; i++){         if(b[i] > 1){             a.push(i);         }     }     return a; }

使用对象,不会有当值很大时这种方案出现的浪费大量空间的情况

function duplicates(arr) {    var obj = {};    var result = [];    //遍历数组,将数组的值作为obj的索引,出现次数为值    arr.forEach(function(item){        if(obj[item]){            obj[item] +=1;        }else{            obj[item] = 1;        }    });    //获取对象自身属性    var propertyNames = Object.getOwnPropertyNames(obj);    //遍历对象,将重复出现的元素取出    propertyNames.forEach(function(item){        if(obj[item] > 1){            result.push(parseInt(item));        }    });    return result;  }

13.求二次方

为数组 arr 中的每个元素求二次方。不要直接修改数组 arr,结果返回新的数组

map

function square(arr) {    return arr.map(function(item,index,array){        return item*item;        //return Math.pow(item,2);    })}

遍历原数组,将其每一个元素求平方,然后存入新的数组即可。
forEach

function square(arr) {   //声明一个新的数组存放结果     var a = [];     arr.forEach(function(e){         //将arr中的每一个元素求平方后,加入到a数组中         a.push(e*e);     });     return a; }

普通for循环

function square(arr) {    var newArr = [];    for(var i=0;i<arr.length;i++){        newArr.push(arr[i]*arr[i]);        //newArr[i] = Math.pow(arr[i],2);    }    return newArr;}

14.查找元素位置

在数组 arr 中,查找值与 item 相等的元素出现的所有位置

//filter

function findAllOccurrences(arr, target) {    var result=[];    arr.filter(function(item,index){        return item===target&&result.push(index);    });    return result;}

//for

function findAllOccurrences(arr, target) {    var result=[];    for(var i=0;i<arr.length;i++){        if(arr[i]===target){            result.push(i);        }    }    return result;}

//lastIndexOf+slice/splice

function findAllOccurrences(arr, target) {    var result=[],index=arr.lastIndexOf(target);    while(index>-1){        result.push(index);        arr.splice(index,1);//arr=arr.slice(0,index);        index=arr.lastIndexOf(target);    }    return result;}

//indexOf

function findAllOccurrences(arr, target) {    var result=[],index=arr.indexOf(target);    while(index>-1){        result.push(index);        index=arr.indexOf(target,index+1);    }    return result;}

使用map和filter

function findAllOccurrences(arr, item) {    return arr.map(function(e, index) {        return e === item ? index : -1;        /* 样例返回结果为[ -1, -1, -1, -1, -1, -1, -1, 0, 6 ] */    }).filter(function(i) {        return i !== -1;        /* 过滤掉 i === -1 的情况 */    })}

函数

1.定时器计时器

1、从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
2、返回的对象中需要包含一个 cancel 方法,用于停止定时操作
3、第一个数需要立即输出

一、通过setInterval()方法

function count(start, end) {  //立即输出第一个值  console.log(start++);     var timer = setInterval(function(){         if(start <= end){             console.log(start++);         }else{             clearInterval(timer);         }     },100);    //返回一个对象     return {         cancel : function(){             clearInterval(timer);         }     }; }

二、通过setTimeout()方法【出自 @shawnan】

function count(start, end) {    if(start <= end){        console.log(start);        start++;        st = setTimeout(function(){count(start, end)}, 100);    }    return {        cancel: function(){clearTimeout(st);}    }}

函数传参

将数组 arr 中的元素作为调用函数 fn 的参数

function argsAsArray(fn, arr) {  return fn.apply(this, arr); }

函数的上下文

将函数 fn 的执行上下文改为 obj 对象
//三种方案
//apply

function speak(fn, obj) {    return fn.apply(obj);}

//call

function speak(fn, obj) {    return fn.call(obj);}

//bind

function speak(fn, obj) {    return fn.bind(obj)();}

二次封装函数

已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件:
1、返回一个函数 result,该函数接受一个参数
2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致

// call和apply必须显式地调用str3,立即执行
// bind不是立即执行,未传入str3时,并未执行,只是返回一个函数,等待参数传入
// this用于上下文不确定的情况

// call

function partial(fn, str1, str2) {    function result(str3) {        return fn.call(this, str1, str2, str3);    }     return result;}

// apply(这里只是为了对照)

function partial(fn, str1, str2) {    function result(str3) {        return fn.apply(this, [str1, str2, str3]);    }    return result;}

// 这个bind会生成一个新函数(对象), 它的str1, str2参数都定死了, str3未传入, 一旦传入就会执行

function partial(fn, str1, str2) {    return fn.bind(this, str1, str2); // 或 return fn.bind(null,str1,str2);}

// bind同上, 多了一步, 把str3传入的过程写在另一个函数里面,
// 而另一个函数也有str1, str2参数
// 此法有种多次一举的感觉,但是表示出了后续的调用。

function partial(fn, str1, str2) {    function result(str3) {        return fn.bind(this, str1, str2)(str3);    }    return result;}

// 匿名函数,默认this绑定global,与bind的第一个参数为this时效果一样。

function partial(fn, str1, str2) {    return function(str3) {        return fn(str1, str2, str3);    }}

// ES6。this指向undefined.

const partial = (fn, str1, str2) => str3 => fn(str1, str2, str3);

使用 arguments

函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。

常规解法

function useArguments() {    var result;    for(var i=0;i<arguments.length;i++){        result += arguments[i];    }   return result;}

转化数组

function useArguments() {    return Array.prototype.reduce.call(arguments,function(prev,curr){        return prev + curr;    });}

Number

二进制转换

获取数字 num 二进制形式第 bit 位的值。注意:
1、bit 从 1 开始
2、返回 0 或 1
3、举例:2 的二进制为 10,第 1 位为 0,第 2 位为 1

通过num.toString(2)能直接将num转换为2进制数格式的字符串,利用下标就能将对应值取出来。题目返回的数字是从右往左,因此下标为倒数。

function valueAtBit(num, bit) {  var s = num.toString(2);     return s[s.length - bit]; }

//

function valueAtBit(num, bit) {    //toString转化为二进制,split将二进制转化为数组,reverse()将数组颠倒顺序    var arr = num.toString(2).split("").reverse();    return arr[bit-1];}

二进制转换

给定二进制字符串,将其换算成对应的十进制数字

function base10(str) {    /**        其它进制转十进制        parseInt(str,2)        parseInt(str,8)        parseInt(str,16)    */    return parseInt(str,2);}

二进制转换

将给定数字转换成二进制字符串。如果字符串长度不足 8 位,则在前面补 0 到满8位。

首先通过toString方法将num转为2进制数形式,然后判断其长度是否足够8位。如不足8位,则声明一个“0000000”字符串用于补0,因为目标的2进制数形式最少为一位,因此最多只需要7个0;通过slice方法对“0000000”进行截取,然后将其结果加在目标前面即可。

function convertToBinary(num) {     //转换为2进制格式     var s = num.toString(2);     //获得2进制数长度     var l = s.length;     if(l<8){         //声明一个字符串用于补满0         var s1 = "0000000";         var s2 = s1.slice(0,8-l);         s = s2+s;      }     return s; }

//

function convertToBinary(num) {    var str = num.toString(2);    while(str.length < 8) {        str = "0" + str;    }    return str;}

//

function convertToBinary(num) {  return ('00000000' + num.toString(2)).slice(-8);}

//

function convertToBinary(num) {  return ('00000000'+num.toString(2)).substr(-8);}

转为二进制后,先除以10的8次方,然后取小数点后的数

function convertToBinary(num) {       var toBit = num.toString(2);       return  ( toBit / Math.pow(10, 8) ).toFixed(8).substr(2);}function convertToBinary(num) {    var str=num.toString(2).split('');    while(str.length<8){        str.unshift(0);    }    return str.join('');}

正则

判断是否包含数字

给定字符串 str,检查其是否包含数字,包含返回 true,否则返回 false

function containsNumber(str) {     var b = /\d/;     return b.test(str); }

//

function containsNumber(str) {    for(var i=0;i<10;i++){        if(str.indexOf(i)!=-1){            return true;        }    }    return false;}

//

function containsNumber(str) {    for(var i=0;i<str.length;i++){        if(Number(str[i])){            return true;        }    }    return false;}

/只要匹配到一个数字,就返回true/

function containsNumber(str) {    var pattern=/\d/g;    if(str.match(pattern))        return true;    else        return false;}

检查重复字符串

给定字符串 str,检查其是否包含连续重复的字母(a-zA-Z),包含返回true,否则返回 false

在正则表达式中,利用()进行分组,使用斜杠加数字表示引用,\1就是引用第一个分组,\2就是引用第二个分组。将[a-zA-Z]做为一个分组,然后引用,就可以判断是否有连续重复的字母。

function containsRepeatingLetter(str) {     return /([a-zA-Z])\1/.test(str); }

//

function containsRepeatingLetter(str) {    var pattern = /[a-zA-Z]/g;    for(var i=0;i<str.length;i++){        if(str[i]==str[i+1] && pattern.test(str[i])){            return true;        }    }    return false;}

判断是否以元音字母结尾

给定字符串 str,检查其是否以元音字母结尾
1、元音字母包括 a,e,i,o,u,以及对应的大写
2、包含返回 true,否则返回 false

首先确定元音集合[a,e,i,o,u],然后是以元音结尾,加上i:/[a,e,i,o,u]/i,最后用test方法去检测字符串str

function endsWithVowel(str) {  return /[a,e,i,o,u]$/i.test(str); }

获取指定字符串

给定字符串 str,检查其是否包含 连续3个数字
1、如果包含,返回最新出现的 3 个数字的字符串
2、如果不包含,返回 false

function captureThreeNumbers(str) {     //声明一个数组保存匹配的字符串结果  var arr = str.match(/\d{3}/);     //如果arr存在目标结果,则返回第一个元素,即最早出现的目标结果     if(arr)         return arr[0];     else return false;     //return arr? arr[0]:false; if语句可用这个代替 }

判断是否符合指定格式

给定字符串 str,检查其是否符合如下格式
1、XXX-XXX-XXXX
2、其中 X 为 Number 类型

本题需要注意格式,开头^和结尾3\d34\d4n/\d3\d3\d4/,有相同部分\d{3}-,因此也可写作/^(\d{3}-){2}\d{4}$/

function matchesPattern(str) {    return/^(\d{3}-){2}\d{4}$/.test(str);}

USD格式

给定字符串 str,检查其是否符合美元书写格式
1、以 23,3241,023,032.03或者2.033,432,12.12或者$34,344.3

首先,开头必是表示结尾,需要进行转义,因此开头为^$

然后$后必然接数字,并且最少一位,最多三位数,可用{m,n}表示,最少m位,最多n位,因此此段为\d{1,3}

接着,后面如还有数,则必然有,分隔,并且后面必有3个数,类似于,XXX的格式会出现0或者n次,因此此段可表示为(,\d{3})*

最后,如有小数部分,则注意对小数点进行转义,此段可表示为(.\d{2})?

因此,最后的正则表达式为/^$\d{1,3}(,\d{3})*(.\d{2})?$/

function isUSD(str) {   return /^\$\d{1,3}(,\d{3})*(\.\d{2})?$/.test(str);}
原创粉丝点击