一、算法之数组去重
方法一:
【简单思路实现】:依次拿出数组的中的每一项,和后面的所有项进行比较,如果有相同的就删除。
var ary=[1,2,3,2,4];
/*
思路:
第一次:
拿出数组的第一项:1
给[2,3,2,4]进行比较,如果有重复就删除
拿出数组的第二项:2
====[3,2,4]进行比较,有重复的删除 [3,4]
拿出数组的第三项:3
===4 进行比较,有重复的删除,没有重复
还用拿最后一项4吗?====不用了
依次拿出数组中的每一项给剩余的所有项进行比较
*/
function unique(ary){
for(var i=0;i<ary.length-1;i++){
var getItem=ary[i];
for(var j=i+1;j<ary.length;j++){
var remainItem=ary[j];
// 如果当前项和后面的项在进行比较的时候,相同就说明重复,要删除掉原数组的那项
if(getItem==remainItem){
ary.splice(j,1);
j--;
}
}
}
return ary;
}
console.log(unique(ary));
【splice造成的数组塌陷问题】
var ary=[1,2,1,3,3,2,3];
for(var i=0;i<ary.length-1;i++){
var current=ary[i];
for(var j=i+1;j<ary.length;j++){
var next=ary[j];
if(current==next){
ary.splice(j,1);
j--;
}
}
}
console.log(ary)
方法二:
【实现的思路】利用对象属性名不重复的思想,先建立一个空对象,然后依次循环数组中的每一项,把此项作为obj对象的属性名和属性值,在添加的时候,如果这个属性名对应的值已经存在,说明此项重复,删除掉此项
/*
var ary2=[1,2,1,3,3,2,3];
利用对象属性名不能重复的原理:对象中如果没有一个属性的时候就是undefined
把数组中的每一项作为一个对象的属性名和属性值
var obj={1:1,2:2,3:3}
原理:如果对象属性中已经存在这个属性名,我们就把原数组中此项进行删除
*/
function unique(ary){
var obj={};
for(var i=0;i<ary.length;i++){
var item=ary[i];
if(typeof (obj[item])!="undefined"){
//如果此时对象的此属性已经有了,我们就应该删除数组中的那一项
ary.splice(i,1);
i--;
continue;
}
obj[item]=item;
}
return ary;
}
var ary2=[1,2,1,3,3,2,3];
var res=unique(ary2);
console.log(res);
【优化方法】:对于数组塌陷,数组中后面所有的数字都要依次改变,这样比较耗性能,怎么优化呢?可以让后面的索引值不变,这样就可以省性能。
把最后一项的值拿过来,占位到塌陷的此项
把最后一项删除
需要注意,此时最后一项也需要比较所以还需要i--;
var ary=[1,2,3,2,3];
var obj={};
for(var i=0;i<ary.length;i++){
var item=ary[i];
if(typeof obj[item]!=="undefined"){
// 把当前重复的项替换成最后一项
ary[i]=ary[ary.length-1];
// 最后一项都已经拿过来了,多余,所以删除掉
ary.length--;
// 此时占位的这一项(最后一项)还没有比较,所以需要i--,再重新比较一次
i--;
continue;
}
obj[item]=item;
}
console.log(ary);
方法三:indexOf
创建一个新数组,遍历原数组,如果新数组中没有那一项的话,就把它push进去
/*
var ary2=[1,2,1,3,3,2,3];
var newAry=[];
把原数组中的每一项,只要在新数组中没存在过,我们就把它放进去,最后newAry就是咱们最终要的数组
*/
function unique(ary){
var newAry=[];
for(var i=0;i<ary.length;i++){
var item=ary[i];
if(newAry.indexOf(item)==-1){
newAry.push(item);
}
}
return newAry;
}
var ary2=[1,2,1,3,3,2,3];
var res=unique(ary2);
console.log(res);
二、算法之冒泡排序
/*
冒泡排序:
从小到大排序
var ary=[8,2,1,5]
原理:依次拿出数组中的每一项给后面的一项做对比,如果当前项比后面的项大就交换位置
第一轮:[2,1,5,8] 经过一轮比较出现了最大数
第二轮:[1,5,2,8] 经过二轮比较得出倒数第2个数
第三轮:[1,5,2,8] 经过二轮比较得出倒数第3个数
.... 总共四项,经过比三轮,已经得到了三个最大数了,最后一个自然就是最小数
【需要比的总轮数】:ary.length-1;
【每次需要比的次数】:ary.length-1-已经比较过的轮数
第一轮:4项两两比较需要比3次:ary.length-1
第二轮: 正常的ary.length-1-已经比较过的轮数
*/
function sort(ary){
// 需要比较的轮数
for(var i=0;i<ary.length-1;i++){
for(var j=0;j<ary.length-1-i;j++){
var current=ary[j];
var next=ary[j+1];
if(ary[j]>ary[j+1]){
// 让 ary[j]=ary[j+1]
var temp=ary[j]
ary[j]=ary[j+1];
ary[j+1]=temp;
}
}
}
return ary;
}
var ary=[8,2,1,5];
var res=sort(ary);
三、递归
自己调自己就是递归;
function fn(num){
fn(num-1)
}
fn(10)
打印1 到10
// 打印1到10
function fn(num){
if(num>10){
return
}
console.log(num);
fn(num+1);
}
fn(1)
[练习题]:求一个1到100的所有数之和
答案一:
/*
1到100中所有数之和
*/
function total(star,end){
var total=null;
for(var i=star;i<=end;i++){
total+=i;
}
return total;
}
var res=total(1,100);
console.log(res);
答案二:递归
function total(num){
if(num>100){
return 0;
}
return num+total(num+1);
}
total(1)
[练习题]:求1到100中同时能被2整除又能被3整除的所有数之和
答案:1
/*
求1-100所有能被2整除又能被3整除的所有数之和
*/
var total=null;
for(var i=1;i<=100;i++){
if(i%2==0&&i%3==0){
total+=i;
}
}
console.log(total);
递归
function total(num){
if(num>100){
return 0;
}
if(num%2==0&&num%3==0){
return num+total(num+1);
}
return total(num+1);
}
var res=total(1);
四、算法之快速排序
/*
快速排序
var ary=[12,15,14,13,16,11];
原理:先拿出中间项,然后把此项从数组中删除掉,让数组中的剩余项一一跟这个中间项做比较,新建两个左右数组,如果大的项就放到右盒子,如果小的项就放到左盒子
[左盒子小]--中间项--[右盒子大]
依次再继续重复相同的步骤,把左盒子和右盒子都进行排序,直到出现空数组或者一项的时候停止
*/
function quickSort(ary){
if(ary.length<=1){
return ary;
}
var centerIndex=Math.floor(ary.length/2);
// 拿到中间项的同时,把中间项从数组中删除掉
var centerValue=ary.splice(centerIndex,1)[0];
// 新建两个数组:leftAry,rightAry;把ary中剩余的项,给中间项做对比,如果大项就放到右数组,小项就放到左数组.
var leftAry=[],rightAry=[];
for(var i=0;i<ary.length;i++){
if(ary[i]<centerValue){
leftAry.push(ary[i]);
}else{
rightAry.push(ary[i]);
}
}
return quickSort(leftAry).concat(centerValue,quickSort(rightAry));
}
var ary=[12,15,14,13,16,11];
var res=quickSort(ary);
五、插入排序
var ary=[34,56,12,66,12];
插入排序:
新建一个数组:依次拿出原数组中的每一项往新数组里面插入,插入的时候需要遵循一个规律:
1)方向:从右向左
2)最终实现的效果,从小到大,在插入的时候,拿出的项
从右向左依次比较(新数组),如果拿出的项大(或者相等),就直接插入首次比它小的后面,
3)如果一直比到第一项了,条件还没满足,后面就是最小项,直接放到数组的最前面
var newAry=[]
第一次====>我拿出第一项直接放进去,不用进行比较
newAry=[34]
第二次====> 拿出56 [34,56]
第三次====> 拿出12 [12,34,56]
第四次=====> 拿出66 [12,34,56,66]
第五次=====> 拿出12 [12,12,34,56,66]
*/
var ary=[34,56,12,66,12];
function insertSort(ary){
//最终排序好的数组盒子
var newAry=[];
//拿出的第一项放进去,此时盒子中只有一项,不用个比较
newAry.push(ary[0]);
// 依次拿出原数组中的每一项进行插入
for(var i=1;i<ary.length;i++){
var getItem=ary[i];
// 在插入的时候需要跟新数组中的每一项进行比较(从右向左)
for(var j=newAry.length-1;j>=0;j--){
var newItemAry=newAry[j];
if(getItem>=newItemAry){
// 如果拿出的项比某项大或者相等,就放到此项的后面
newAry.splice(j+1,0,getItem);
// 插入完毕,不用再继续比较停止循环;
break;
}
if(j==0){
//如果都已经比到第一项了,还没满足条件,说明这个就是最小项,我们之间插入到数组的最前面
newAry.unshift(getItem);
}
}
}
return newAry;
}
var res=insertSort(ary)
字符串
一、字符串的方法
@1、charAt
通过下标去取值
var str = 'chengxiaohui';
// 通过下标取值
var res = str.charAt(0);//"c"
// 如果找不到,返回值是空串
var res2 = str.charAt(12);//""
// 如果直接是索引去取值,找不到,返回是undefined
var res3 = str[12];//undefined
@2、charCodeAt
通过下标取值对应的ascii码值
var str = 'chengxiaohui';
// 通过下标取值
var res = str.charCodeAt(0);//99 "c"==>ASCII码
console.log(res);//99
@3、indexOf/lastIndexOf
第一个参数:找的内容
第二个参数:开始找的位置(indexOf)/找到哪终止(lastIndexOf)
一个参数的情况indexOf
var str = 'chengxiaohui';
// 一个参数,在整个字符串中找
var res = str.indexOf("x");
// 返回值是找到的下标
console.log(res);//5
lastIndexOf
var str = 'chengxiaohui';
// 一个参数,在整个字符串中找最后一次出现的下标
var res = str.lastIndexOf("h");
// 返回值是找到的下标
console.log(res);//9
两个参数的情况:indexOf
var str = 'chengxiaohui';
// 从下标5开始找,找"h"
var res = str.indexOf("h",5);
// 返回值是找到的下标
console.log(res);//9
lastIndexOf
var str = 'chengxiaohui';
// 截止到下标5,找"h"
var res = str.lastIndexOf("h",5);
// 返回值是找到的下标
console.log(res);//1
@4、slice
作用:查找字符串中特定位置的字符
参数:(n,m) n:起始索引(包含), m结束索引(不包含)
返回值:查找的字符●从索引n(包括)开始查找到索引m(不包含)结束的字符●如果索引m不写,就是查找到最后●如果n只写一个0,或者不写就是复制一份●也可以为负数,转换成正数的规律:str.length+负的索引值
var str="zhufengpeixun"
str.slice(1,3) ===>"hu"
str.slice(0) ===>复制一份
str.slice() ===>复制一份
var res=str.slice(-3,-1); ===>“xu”
@4.1、substring(n,m)
subString 和slice 基本都一样,唯一不同在于,subString 不支持负数索引,而slice支持负数索引
@4.2、substr(n,m)
●作用:从索引n开始截取m个字符●参数:n,m(个数)●返回值:截取的字符串●也支持从负索引开始
var str="zhufengu";
var res=str.substr(-3,2); ====>"ng"
@5、 toUpperCase()
toUpperCase(); 把字符串转换为大写
@6、 toLowerCase()
toLowerCase(); 把字符串转换为小写
@7、 replace()
作用:把字符串中某部分的字符替换成另一部分字符
参数:(str1,str2)第一个参数代表的是要替换的字符或者是正则;第二个参数代表的是替换后的字符
返回值:替换后的字符串
var str="zhufeng2018zhufeng2019zhufeng";
var res=str.replace("zhufeng","珠峰");
//===>"珠峰2018zhufeng2019zhufeng"
var res=str.replace(/zhufeng/g,"珠峰");
console.log(res)===>"珠峰2018珠峰2019珠峰"
@8、split()
作用:按照指定的字符把字符串分割成数组
参数:分割符
返回值:分割后的数组
split 和 join 对比记忆
var str="1-2-3";
var res=str.split("-");
console.log(res); ===> ["1", "2", "3"]
二、练习题
1【时间字符串处理】把下面的字符串变成 "2019年08月18日 12时32分18秒"
var str="2019-8-18 12:32:18";
//var res=str.split(/-| |:/g)
var time=str.split(" ");
console.log(time) //["2019-8-18", "12:32:18"]
var timeLeft=time[0];
var timeRight=time[1];
var ary1=timeLeft.split("-"); // ["2019", "8", "18"]
var ary2=timeRight.split(":");// ["12", "32", "18"]
var result=ary1[0]+"年"+ary1[1]+"月"+ary1[2]+"日"+" "+ary2[0]+"时"+ary2[1]+"分"+ary2[2]+"秒"
console.log(result) //"2019年8月18日 12时32分18秒"
/*
补零
*/
function zero(num){
return num<10?"0"+num:num;
}
var ss=zero(11);
var result=zero(ary1[0])+"年"+zero(ary1[1])+"月"+zero(ary1[2])+"日"+" "+zero(ary2[0])+"时"+zero(ary2[1])+"分"+zero(ary2[2])+"秒"
//"2019年08月18日 12时32分18秒"
2、queryURLParams 问号参数处理
/*
var str ="https://www.baidu.com?name=zhufeng&age=10&id=14";
{
name:"zhufeng",
age:10,
id:14
}
*/
function urlParams(str){
var obj={};
var paramsStr=str.split("?")[1];
if(paramsStr){
//[name=zhufeng,age=10,id=14]
var paramsAry=paramsStr.split("&");
for(var i=0;i<paramsAry.length;i++){
//name=zhufeng
var item=paramsAry[i];
//[name,zhufeng]
var itemAry=item.split("=");
obj[itemAry[0]]=itemAry[1];
}
}
return obj;
}
var str ="https://www.baidu.com?name=zhufeng&age=10&id=14";
var result= urlParams(str);
三、Math常用的方法
Math称之为数学函数,它也是对象类型数据,主要是用来操作数字的
1)Math.abs() 求绝对值 // Math.abs(-1)
2)Math.ceil/Math.floor
向上取整,向下取整向上取整,无论是正数还是负数,都取最大的值向下取整,无论是正数还是负数,都取最小的值
Math.ceil(1.2)
2
Math.ceil(-1.6)
-1
Math.floor(1.8)
1
Math.floor(-1.1)
-2
3)Math.round() 四舍五入
正数的话,还是正常的,之前理解的,但是如果是负数,临界点必须大于5
Math.round(1.5)
2
Math.round(-1.5)
-1
Math.round(-1.51)
-2
4)Math.sqrt() 开平方
Math.sqrt(9)
3
5)Math.pow(n,m) 取幂n的m次幂
Math.pow(3,2) ==> 9
6)Math.PI
Math.PI ===>3.141592653589793
7)Math.max/Math.min 获取最大值和最小值
Math.max(1,2,3)
Math.min(4,5,6)
8)Math.random() 获取0~1 之间的随机数(大于等于0,小于1)
获取n 到m 之间的随机数:Math.random()*(m-n)+n;// 获取10 到20 之间的随机数
Math.random()*10+10
[升级版2]如果传的实参中包含字符串,就变成数字,如果是非有效数字,就直接略过
function fn(){
var total=null;
for(var i=0;i<arguments.length;i++){
var item=Number(arguments[i]);
isNaN(item)?null:total+=item
}
return total;
}
[高级版3:es6]
functionfn(...arg){
returneval(arg.filter((item)=>!isNaN(item)).join("+"))
}
varres=fn(1,2,3,"3","3px");