第四节 数组去重和字符串 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");

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容