文章目录
数组
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);
}
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;
}
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);
}