数组

191 阅读11分钟

数组

字面理解就是一组数据的集合

js的数组成员可以是任意类型的数据

数组可以动态扩容

创建数组

字面量创建(推荐使用)

语法:
    var 数组名 = []
    
注:
    数据之间用","隔开

例:
    var arr = [11,22,33,44]
    console.log(arr)  //(4) [11, 22, 33, 44]

构造函数创建

语法:
    var 数据名 = new Array()    

例:
    var arr = new Array(11,22)
    console.log(arr)  //(2) [11, 22]
    var arr = new Array(10)
    console.log(arr)  //(10) [empty × 10]

注:
    如果Array里有一个参数,并且是数值类型,表示数组的初始值长度,值都为empty(空)    

数组长度与下标

获取数组长度

语法:
    语法:数组名.length 
例:
    var arr = [11,22,33,44,55]
    console.log(arr.length)  //5

注:数组长度可以被修改,**会丢失数据**

例:
    var arr = [11, 22, 33, 44];
    arr.length = 1;
    console.log(arr)  //[11]
    arr.length = 4;
    console.log(arr);  //(4) [11, empty × 3]

下标(索引)

语法:数组名[下标值]

  • 通过数组的下标可以获取或修改指定位置的元素
  • 下标的取值范围为0~数组长度-1
// 索引从0开始
var arr = [11, 22, 33]
// 通过下标取值
console.log(arr[1])  //22
// 通过下标修改值
arr[0] = "aaa"
console.log(arr)  //(3) ['aaa', 22, 33]

数组方法

  • 常用方法:20个

    es3(10个)pop,push,shift,unshift,sort,reverse,slice,splice,concat,join

    es5高阶函数(6个)forEach,map,some,every,filter,reduce

    es6(3个)find,findIndex,includes

    indexOf

Es3

pop()

  • 删除数组的最后一位
  • 返回被删除的元素
  • 会改变原数组
var arr = [11, 22, 33, 44]
console.log(arr)  //(4) [11, 22, 33, 44]
var res = arr.pop()
console.log(res)  //44
console.log(arr)  //(3) [11, 22, 33]

push()

  • 往数组的最后位置添加元素(1个或多个)
  • 返回数组的新长度
var arr = [11, 22, 33, 44]
console.log(arr)  //(4) [11, 22, 33, 44]
var res = arr.push("刘德华", "111")
console.log(res)  //6
console.log(arr)  // [11, 22, 33, 44, '刘德华', '111']

shift()

  • 删除数组的第一位元素
  • 返回被删除的元素
var arr = [11, 22, 33, 44]
console.log(arr.shift())  //11
console.log(arr)  //(3) [22, 33, 44]

unshift()

  • 往数组的第1个位置添加元素(1个或多个)
  • 返回数组的新长度
var arr = [11, 22, 33, 44]
console.log(arr.unshift("111", "BBB"))  //6
console.log(arr)  //(6) ['111', 'BBB', 11, 22, 33, 44]

sort()

  • 排序
  • 默认是根据ASCII码,进行比较
  • a-b 升序
  • b-a 降序
var arr = [5, 67, 85, 1, 60, 23]
arr.sort(function (a, b) {
   // return a-b  //升序
   return b - a  //降序
})
console.log(arr)  //(6) [85, 67, 60, 23, 5, 1]

reverse()

  • 倒序
var arr = ["aa", "bb", "cc", "dd"]       
console.log(arr.reverse())  //(4) ['dd', 'cc', 'bb', 'aa']

slice()

  • 截取
  • slice(开始索引,结束索引)
  • 包含开始索引,不包含结束索引
  • 返回一个新数组,不会影响原数组
  • ()里面不写值,表示截取数组中的所有元素
var arr = [11, 22, 33, 44, 55, 66]

//截取数组下标为2和4之间的元素,包含下标为2的元素,不包含下标为4的元素
var res1 = arr.slice(2, 4)  
console.log(res1)  //(2) [33, 44]
console.log(arr)  //(6) [11, 22, 33, 44, 55, 66]

//截取数组下标为2和2之后的所有元素
var res2 = arr.slice(2)
console.log(res2)  //(4) [33, 44, 55, 66]

//复制arr数组
var res3 = arr.slice()
console.log(res3)  //(6) [11, 22, 33, 44, 55, 66]

splice()

  • splice(开始元素,删除元素,"插入元素")
  • 会改变原数组,返回一个数组
var arr = [11, 22, 33, 44, 55, 66]

// 2个参数,删除 返回被删除的元素,并且是以数组的方式返回
var res = arr.splice(3, 2)  
console.log(res)  //(2) [44, 55]
console.log(arr)  //(4) [11, 22, 33, 66]

// 3个参数:如果第二参数是0,插入;如果是1或1以上,替换
    // 插入
var arr = [11,22,33,44,55,66,77,88]
var res= arr.splice(4,0,'aa',"bb")
console.log(res)  //[]
console.log(arr)  //(10) [11, 22, 33, 44, 'aa', 'bb', 55, 66, 77, 88]
    // 替换
var arr = [11,22,33,44,55,66,77,88]
var res = arr.splice(4,2,"aa","bb")
console.log(res)  //(2) [55, 66]
console.log(arr)  //[11, 22, 33, 44, 'aa', 'bb', 77, 88]

concat()

  • 拼接
  • 不会影响原数组,返回一个新数组
var arr1 = [11,22,33]
var arr2 = [44,55,66]

//拼接arr1和arr2
var res = arr1.concat(arr2)
console.log(res)  //(6) [11, 22, 33, 44, 55, 66]

//复制数组arr1
var res = arr1.concat()
console.log(res)  //(3) [11, 22, 33]

//拼接arr1 + arr1 + "aa" + 33
var res = arr1.concat(arr2,"aa",33)
console.log(res)  //(8) [11, 22, 33, 44, 55, 66, 'aa', 33]

join()

  • 默认用,隔开
  • 返回一个字符串
var arr = [2020,12,12]
console.log(arr.join())     //2020,12,12
console.log(arr.join("-"))      //2020-12-12
console.log(arr.join("/"))      //2020/12/12

高阶函数:

item:数组中的元素

index:元素下标

arr:数组

forEach()

  • 遍历
  • 只能做遍历,没有返回值,不能被中断
  • 可以制造异常,结合try...catch中断
var arr = [11, 22, 33, 44, 55, 66]
arr.forEach(function(item,index,arr){  
    console.log(item,index,arr)
})

image.png

制造异常中断

try {
    arr.forEach(function (item, index, aaa) {
        console.log(item, index, aaa)
        if (index == 1) {    //数组下标为1时,中断遍历
            throw new Error("制造异常中断")
        }
    })
} catch (Error) {

}

image.png

map()

  • 映射
  • 有返回值,返回一个新数组,不会改变原数组
  • 把数组中的每一个元素做相同的事情
var arr = [1,2,3,4,5]
var res = arr.map(function (item, index, arr) {
    return item * 10
})
console.log(res)  //(5) [10, 20, 30, 40, 50]

some()

  • 一个
  • 只要有一个满足条件,就返回true,默认返回false
  • 在遍历的过程中,只要条件满足,就中断遍历
var arr = [11, 22, 33, 44, 55, 66]
var res = arr.some(function (item, index, arr) {
    return item == 33
})
console.log(res)  //true

every()

  • 每个
  • 所有元素都满足条件,才会返回true,默认返回false
var arr = [11, 22, 33, 44, 55, 66]
var res = arr.every(function (item, index, arr) {
    return item > 30
})
console.log(res)  //false

var res = arr.every(function (item, index, arr) {
    return item > 10
})
console.log(res)  //true

filter()

  • 过滤
  • 只能判断为falsetrue,为true时才返回当前元素
  • 返回值:找到数组中所有符合条件的元素,并以数组的方式返回
var arr = [11, 22, 33, 44, 55, 66]
var res = arr.filter(function (item, index, arr) {
    return item > 30
})
console.log(res)  //(4) [33, 44, 55, 66]

reduce()

  • 归并
  • pre始终为上一次return计算的结果
  • 有2个参数
    • 第1个参数是回调函数,有4个形参
      • pre 上一次回调函数的返回结果或者reduce的初始值
      • cur 当前的元素
      • index 下标
      • arr 原来的数组
    • 第2个参数,给第1个pre的初始值
  • 【注】
    • 从左往右执行,也就是索引从小到大执行
    • 在reduce回调函数中,我们要先给定pre一个值,不然会出现pre取到数组下标为0的元素,cur只能从下标为1开始取值
var arr = [11, 22, 33, 44, 55]
var res = arr.reduce(function (pre, cur, index, arr) {
    return pre + cur
},0)
console.log(res)  //165

Es6

find()

  • 查找
  • 通过条件,查找某一项,如果存在就返回这一项
  • 只能查找出一个符合条件的值
  • 找到了返回该项,没找到返回undefined
var arr = [
    { id: 1, name: "aaa", age: 18 },
    { id: 2, name: "bbb", age: 20 },
    { id: 3, name: "ccc", age: 20 },
    { id: 4, name: "ddd", age: 18 },
]
var res = arr.find(function (item) {
    return item.name == "bbb"
})
console.log(res)  //{id: 2, name: 'bbb', age: 20}

findIndex()

  • 查找
  • 返回满足条件的某一项的下标
  • 只能查找出一个符合条件的值
  • 找到了返回该下标,没找到返回-1
var arr = [
    { id: 1, name: "aaa", age: 18 },
    { id: 2, name: "bbb", age: 20 },
    { id: 3, name: "ccc", age: 20 },
    { id: 4, name: "ddd", age: 18 },
]
var res = arr.findIndex(function (item) {
return item.age == 20
})
console.log(res)  //1

includes

  • 包含
  • 找指定的内容
  • 找到了返回true,没有找到返回false
var arr = [11, 22, 33, 44, 55, 22, 11, 99]
console.log(arr.includes(222))  //false
console.log(arr.includes(22))   //true

indexOf()

  • 找指定的内容,返回要查询的内容的下标
  • 语法:数组 . indexOf ( " 要查找的内容 ",开始查找的元素下标 )
  • 开始查找的元素下标默认从0开始,也可以指定开始位置
  • 注:
    • -1表示没有该内容
    • 假若数组中有多个相同的值,返回的结果为查找到的第一个值的索引
var arr = [11, 22, 33, 44, 55, 22, 11, 99]
console.log(arr.indexOf(22))  //1
console.log(arr.indexOf(88))  //-1
console.log(arr.indexOf(22, 2))  //5

排序

冒泡排序

  • 口诀:
    • 外层循环-1
    • 内层循环-1又-i
    • 相邻的两个数比较大小
  • 问:
1.为什么外循环要-1?
    因为两个数只要比较1次,五个数只要比较4次
2.为什么内循环要-1又减- i;
    -1防止下标越界,j+1,容易出现下标越界
    -i是因为每一轮比较都会出现一个最大数或最小数,这个数字不用再参与比较
3.比较的时候,为什么是j和j+1;
    前一个数和后一个数,比较
  • 代码:
var arr = [6, 5, 2, 3, 1, 7]
// 2个数,比较1轮,同理6个数,比较5轮
for (var i = 0; i < arr.length - 1; i++) {
    // -1防止下标越界 j+1容易出现越界
    for (var j = 0; j < arr.length - 1 - i; j++) {
        // 前一个数和后一个数比较 ,比较arr[j]  和 arr[j+1]
        if (arr[j] > arr[j + 1]) {
            var temp = arr[j + 1]
            arr[j + 1] = arr[j]
            arr[j] = temp
        }
    }
}
console.log(arr)  //(6) [1, 2, 3, 5, 6, 7]

选择排序

  • 外层循环-1
  • 假定每次下标为i的都为最大(最小)值
  • 内层循环:下标为i的元素不用再跟自身进行比较,所以j=i+1
var arr = [6,2,1,4,3,5]
for(var i=0;i<arr.length-1;i++){
    //假定每次下标为i的都为最小值
    var minIndex = i
    //下标为i的元素不用再跟自身进行比较,所以j=i+1
    for(var j=i+1;j<arr.length;j++){
        //如果遇到比假定数值还小的数,就把下标进行替换
        if(arr[minIndex]>arr[j]){
            minIndex = j  
        }
    }
    //内层for循环结束后,就会得到一个最小值的下标
    //判断假定的下标值有没有被修改,
    //   没有被修改就继续循环,
    //   被修改了就定义一个临时变量进行交换,把最小值赋值给arr[i],然后继续循环
    if(minIndex != i){
        var temp = arr[i]
        arr[i] = arr[minIndex]
        arr[minIndex] = temp
    }
}
console.log(arr)  //(6) [1, 2, 3, 4, 5, 6]

快速排序

  • 采用了分治法和利用了递归的原理
var arr = [6,2,1,4,3,5]
//定义一个方法,传入一个数组
function quickSort(list){
    // 如果传入的不是数组,就返回一个空数组
    if(!Array.isArray(list)){
        return []
    }
    // 如果数组的长度小于2(数组中只有一个数),就返回原数组
    if(list.length<2){  //递归的临界值
        return list
    }
    //找出中间下标
    //遇到不能整除的要向下取整,使用parseInt或者floor
    //不能向上取整,向上取整可能会导致下标越界
    var middelIndex = parseInt(list.length/2)
    //通过中间下标,得到中间数,并且从原数组中取出来
    var middelVal = list.splice(middelIndex,1)
    //准备2个空数组,中间数左边和右边的空数组
    var left=[],right=[]
    for(var i=0;i<list.length;i++){
        if(list[i]>middelVal){
            //大于中间数的元素,放right数组中
            right.push(list[i])
        }else{
            //小于中间数的元素,放left数组中
            left.push(list[i])
        }
    }
    //递归继续拆解left,right数组,拆到数组内的元素都只有1个数,就不拆解了
    //最后进行合并,左边的数组 + 中间数 + 右边的数组
    return quickSort(left).concat(middelVal,quickSort(right))
}
console.log(quickSort(arr))  //(6) [1, 2, 3, 5, 6, 7]

数组的遍历

  • 稀疏数组:数组中有些元素是空的,空的值默认是undefined
  • 例:var arr = ['张三',,,'李四',,'王五','赵六']

for循环

  • 通过下标获取值
  • 如果遍历稀疏数组时,undefined会被遍历出来
var arr = ['张三','李四','王五','赵六']
for(var i=0;i<arr.length;i++){
    console.log(arr[i])
}

for...in

  • 通过下标获取值
  • 语法:for(var key in 数组名){}
  • 如果遍历稀疏数组时,undefined不会被遍历出来
var arr = ['张三','李四','王五','赵六']
for(var key in arr){
    console.log(arr[key])
}

for...of

  • 直接获取值
  • 语法:for(var value of 数组名){}
  • 如果遍历稀疏数组时,undefined会被遍历出来
  • value直接获取数组元素
var arr = ['张三','李四','王五','赵六']
for(var value of arr){
    console.log(value)
}

数组去重方法

利用对象的key值

  • 原理:在对象中相同的key值会覆盖
var arr = [1,2,2,4,5,3,1,4,2]
var obj = {}
for(var i=0;i<arr.length;i++){
    obj[arr[i]] = ""   //使用对象key值相同会被覆盖的原理
}
var arr1 = []
for(var key in obj){
    //遍历对象obj,把对象中的key值转为number类型,在push()追加在arr1数组中    
    arr1.push(Number(key))  
}
console.log(arr1)  //(5) [1, 2, 3, 4, 5]

利用indexOf === -1

  • indexOf===-1说明数组中没有这个元素
var arr = [1,2,2,4,5,3,1,4,2]
var arr1 = []
for(var i=0;i<arr.length;i++){
    if(arr1.indexOf(arr[i]) === -1){
        arr1.push(arr[i])
    }
}
console.log(arr)  // [1, 2, 2, 4, 5, 3, 1, 4, 2]
console.log(arr1)  // [1, 2, 4, 5, 3]

双重for循环

  • 会改变原数组
  • 【注】:删除之后,数组元素将少一个,所以要j--
var arr = [1,2,2,2,1]			
for(var i=0;i<arr.length;i++){
    for(var j=i+1;j<arr.length;j++){
        if(arr[i] == arr[j]){ 
            arr.splice(j,1)
            //删除之后,数组元素将少一个
            //为了抵消再次累加后跳过的索引
            j--
        }
    }
}
console.log(arr)  //[1,2]

new Set

  • ES6中新出的,最简单的数组去重方法
var arr = [1,2,2,4,5,3,1,4,2]
var set1 = new Set(arr)
console.log(set1)   //Set(5) {1, 2, 4, 5, 3}
var arr1 = Array.from(set1)
console.log(arr1)   //(5) [1, 2, 4, 5, 3]