第四节 数组去重和字符串 Math方法

一、算法之数组去重

方法一:

【简单思路实现】:依次拿出数组的中的每一项,和后面的所有项进行比较,如果有相同的就删除。

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");

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容