牛客网js学习总结

数组

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。因此正则表达式为:/[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个数可表示为\d{3},4个数则为\d{4},{n}表示前面内容出现的次数。正则表达式可写作/^\d{3}-\d{3}-\d{4}$/,有相同部分\d{3}-,因此也可写作/(\d{3}-){2}\d{4}$/

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

USD格式

给定字符串 str,检查其是否符合美元书写格式
1、以 $ 开始
2、整数部分,从个位起,满 3 个数字用 , 分隔
3、如果为小数,则小数部分长度为 2
4、正确的格式如:$1,023,032.03或者$2.03错误的格式如:$3,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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值