数组方法与日常应用

86 阅读10分钟

前言

前段时间去面试,上来就给我搞了几个算法题,虽然不是很难,但是在当时的环境下并没有做出来,有的就算有思路,也是模模糊糊的,经不起推敲。最近开始在刷算法题,发现自己基础不扎实,有些概念知道,但是用起来就有点模棱两可,所以先从数组开始再温习一下知识点,加深一下印象,继续刷题!

我们从几方面对这些方法进行了解学习,如果用法差不多的,放一块对比学习
1 基本用法
2 对源数组的影响
3 日常应用

按照字母顺序从A开始

1 at

如果不是这次打印数组去看原型方法,还注意不到 at 的存在。属于 es13 的新增 基本用法:用来获取数组上某个位置的元素。开始下标从 0 开始,最后一个用倒叙可以使用 -1 取值,查找到则返回该元素,查不到则返回 undefined
影响: 对原数组无影响!
应用: 我们平常获取某个位置的元素会使用 index ,获取最后一个元素时使用 length-1 ,我们来看下 at 的实现

let arr=[1,2,3,4,5]
//使用index
arr[0]            //第一个
arr[arr.lenght-1] //倒数第一
arr[arr.lenght-2] //倒数第二

//使用at
arr.at(0)  //第一个
arr.at(-1) //倒数第一
arr.at(-2) //倒数第二
arr.at(-2222) //undefined

2 concat

基本用法: 数组拼接,参数可以是一个或者多个数组,返回组成的数组
影响: 对源数据浅拷贝。不太了解赋值,浅拷贝,深拷贝的小伙伴可以看我之前的文章 juejin.cn/post/721216… 应用:

const arr1: any = [1, 2, 3]
// const arr2: any = arr1.concat([4, 5, 6])
// arr2[0] = 11
// console.log(arr1)
// console.log(arr2) // 这样看下来似乎是对源数据无影响,我们继续测试

// const arr3: any = [{ id: 1 }, { id: 2 }, { id: 3 }]
// const arr4: any = arr3.concat([{ id: 4 }])
// arr4[0].id = 11
// console.log(arr3)
// console.log(arr4) // 我们看到数组三被修改了,所以concat 也仅仅是一层浅拷贝而已

3 copyWithin fill

copyWhihin

基本用法: 从名字中就可以知道大概意思,在数组中某个地方进行拷贝 copyWithin 接收三个参数 Array.prototype.copyWithin(target, start=0, end = this.length) target: 从该位置开始替换数据
start: (可选):从该位置开始读取数据,默认为 0 。如果为负值,表示倒数 end: (可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数

fill

基本用法: 数组填充,和 copyWhihin 用法基本相同,不过第一个参数是要填充的数据,后两个参数用法一样
影响: copyWithin 和 fill 都会改变源数组,不过 copyWithin 不同的是copy超出后会把数组进行截取,保持原来数组的长度
应用: 我们来简单看下使用

const arr = [1, 2, 3, 4, 5]
 const arr2 = arr.copyWithin(1, 0)  //[1, 1, 2, 3, 4]
//从1号下标2开始进行填充,填充数据 0 号下标开始到4号下标结束,超出了长度,所以会进行截取
const arr3 = arr.copyWithin(0, -3, -4) // [1, 2, 3, 4, 5]
const arr4 = arr.copyWithin(0, -4, -3) // [2, 2, 3, 4, 5]
//虽然可以为负数,但是不能从右侧往左侧进行拷贝,否则不生效,
const arr5 = arr.fill(22, 2, 3) // [1, 2, 22, 4, 5]

4 keys() values() entries()

基本用法: 遍历数组。分别是遍历keyvalue,和 key 以及 value
影响: 因为是直接进行源数据遍历,修改 value 会直接对数据产生影响
应用:

const arr = [1, 2, 3, 4, 5]
for (const index of arr.keys()) {
  console.log(`index==${index}`)
}
for (const value of arr.values()) {
  console.log(`value=${value}`)
}
for (const [index, value] of arr.entries()) {
  console.log(`index==${index},value=${value}`)
}

5 filter

基本用法: 遍历数组,过滤出返回值为true 的数据,返回一个新数组。接收一个函数为参数,该函数有三个参数,value, index ,源数组
影响: 对源数据无影响
应用: 获取符合条件的数据,比如过滤 id >= 2 的数据,删除 id ===1

const list = [
  { id: 1, name: '111' },
  { id: 2, name: '222' }
]
const arr2 = list.filter((item, index, arr) => {
  console.log(item)
  console.log(index)
  console.log(arr)
  return item.id >= 2
})
console.log(arr2)
arr2.push({ id: 3, name: '333' })
const arr4=arr2.filter(item=>item.id!==1)
console.log(list)

find, findIndex, findLast, findLastIndex

基本用法:
find 查询符合条件的第一条数据(正序查询),有则返回该数据,无则返回 undefined
findIndex 查询符合条件的第一条数据(正序查询)的下标,有则返回该数据的下标,无则返回 -1findLast, findLastIndex 对应 findfindIndex 倒序查询 不过这个两个属于 ES14 的提案
参数: 和 filter 参数一样
影响: 对源数据无影响
应用:

const arr = [1, 2, 3, 4, 5]
const vlaue = arr.find((item) => item > 3)  
const vlaue2 = arr.findLast((item) => item > 3)
const index = arr.findIndex((item) => item > 3)
const index2 = arr.findLastIndex((item) => item > 3)

flat

基本用法:对数组进行展开。arr.flat(depth) depth 默认等于1 es10 新增
影响: 返回新数组,对源数组无影响
应用: 根据条件拉平数组

const arr = [1, 2, 3, 4, , 5, [33, 55, [66, 77, [88, 99]]]]
const arr2 = arr.flat() / 不传递参数的时候默认为一层,当数组里面有空项的时候,会过滤掉空值
const arr2 = arr.flat(Infinity) //传入 Infinity 进行N维数组展开

flatMap

基本用法:flatMap是数组的一个新方法,它会遍历原数组的每一个元素, 并且会为每个元素都执行一次传入的回调函数,最终把所有元素执行回调函数返回的结果压缩成一个新数组,与 filter 参数相同
影响:flatMap 会返回一个新的数组,不会改变原数组
应用: 使用 filter 与 map 才可以完成的功能,flatMap 可以直接实现

const arr = [
  {
    id: 1,
    name: '测试1'
  },
  {
    id: 2,
    name: '测试2'
  },
  {
    id: 3,
    name: '测试2'
  }
]
// 删除数据
const arr2 = arr.flatMap((item) => (item.id >= 2 ? [item] : [])) 类似于filter操作
//修改数据
const arr3=arr.flatMap(item=>{item.id*=2;return [item]})  类似于map操作
//过滤同时修改数据
const arr4 = arr.flatMap((item) => (item.id >= 2 ? [{uuid:item.id*item.id,message:item.name}] : []))
//使用filter 和 map
const arr5 = arr.filter((item) => item.id >= 2).map((item) => ({
    uuid: item.id * item.id,
    message: item.name
  }))

forEach

基本用法:数组遍历,参数同 filter 无法提前结束循环
影响: 无返回值,对源数组无影响
应用: 数组遍历

const arr = [1, 2, 3, 4, 5]
arr.forEach((element) => {
  if (element === 2) {
    element = 22
  }
  if (element >= 3) {
    return false
  }
})

includes , indexOf, lastIndexOf

基本用法:查询某个元素是否存在 两个参数 arr.includes(searchElement,fromIndex?) searchElement 查找的值,fromIndex 从某个位置开始查找 includes 返回值为布尔 剩余两个查到返回下标,查询不到返回-1
影响:对源数组无影响
应用: 数组某个值查询

const arr:any = [1, 2, 3, 4, 5, 2]
arr.includes('2')
arr.indexOf(2)
arr.lastIndexOf(2)

join

基本用法arr.join() 将数组拼接成字符串
影响: 对源数组无影响
应用:

const arr = [11, 22, 33]
const str = arr.join('') //112233

map

基本用法:map()方法按照原始数组元素顺序依次处理元素,返回一个新数组,数组中的元素为原始数组元素调用函数处理的后值。参数同 filter
影响: 不会对空数组进行检测,不会改变原始数组
应用: 如对返回的数据自定义处理

const arr = [
  {
    id: 1,
    name: '测试1'
  },
  {
    id: 2,
    name: '测试2'
  },
  {
    id: 3,
    name: '测试3'
  }
]
const ids = arr.map((item) => item.id)
const newArr = arr.map((item) => ({
  key: item.id,
  value: item.name
}))

pop push shift unshift

基本用法
push: 该方法是向数组末尾添加一个或者多个元素,并返回新的长度。 unshift 数组开头添加元素。
pop: pop()方法刚好和push()方法相反。pop()方法删除数组的最后一个元素,把数组的长度减1,返回它被删除元素的值,如果数组变为空,则该方法不改变数组,返回undefine值 shift 数组开头删除元素
影响: 改变原始数组
应用:

const arr = [
  {
    id: 1,
    name: '测试1'
  },
]
arr.pop()
arr.push(
  {
    id: 2,
    name: '测试2'
  },
  {
    id: 3,
    name: '测试3'
  }
) //参数可以为多个对象
arr.shift()
arr.unshift({
  id: 33,
  name: '测试33'
})

reduce reduceRight

基本用法
reduce: reduce() 方法对数组中的每个元素进行遍历,返回值作为下一次循环的初始值,最终返回处理的结果。arr.reduce((pre, current, index, arr) => {}, init) prev: 必需。累计器累计回调的返回值; 表示上一次调用回调时的返回值,或者初始值 init
cur: 必需。当前正在处理的数组元素;
index: 可选。当前正在处理的数组元素的索引,若提供 init 值,则起始索引为 0,否则起始索引为 1
arr: 可选。表示原数组;
init:可选。表示初始值。
影响: 返回 pre 值 如果对修改 current arr会改变源数组
应用: 比如数组求和、数组中元素出现的次数、数组去重

const arr = [1, 2, 3]
// 数组求和
const total = arr.reduce((pre, current) => pre + current, 0)
//数组中元素出现的次数
const arrCount = arr.reduce((pre, current) => {
  const index = pre.findIndex((item) => item.value === current)
  if (index === -1) {
    pre.push({
      count: 1,
      value: current
    })
  } else {
    pre[index].count += 1
  }
  return pre
}, [])
//数组去重
const arrFilter = arr.reduce((pre, current) => {
  if (!pre.includes(current)) {
    pre.push(current)
  }
  return pre
}, [])

reverse

基本用法:数组翻转 如[1, 2, 3, 4] 转换为[4, 3, 2, 1]
影响: 返回翻转后的数组,改变源数组
应用: 比如在算法中判断一个字符串是否为回文数(正写倒写都一样)

const reverseStr = (str) => {
  let str2 = [...str]
  str2 = str2.reverse()
  str2 = str2.join('')
  return str === str2
}
console.log(reverseStr('abcdcba'))
console.log(reverseStr('abcdcacacba'))

slice

基本用法:数组切片 arr.slice(start,end) start 为开始下标 (包括) end 为结束下标(不包括) 返回被切片的数组,如果下标为负数,则倒叙。无论正序还是倒序只能从左到右,否则返回空数组
影响: 浅拷贝数组
应用:

const arr = [
  { id: 1, name: '测试1' },
  { id: 2, name: '测试2' }
]
const arr2 = arr.slice(-1, -2) // []
const arr3 = arr.slice(0, 1) // [{ id: 1, name: '测试1' }]
arr3[0].id = 333  //arr 数据也被改变

sort

基本用法:数组切片 arr.slice(start,end) start 为开始下标 (包括) end 为结束下标(不包括) 返回被切片的数组,如果下标为负数,则倒叙。无论正序还是倒序只能从左到右,否则返回空数组
影响: 返回排序后的数组,改变源数组
应用: 数组排序

const arr = [1, 3, 11, 33, 22, 88]
arr.sort() // [1, 11, 22, 3, 33, 88] 如果省略,则元素按升序、ASCII字符顺序排序。
arr.sort((a, b) => a - b) // [1, 3, 11, 22, 33, 88]

const arr2 = [  {    name: '李白',    price: 18888  },  {    name: '妲己',    price: 5888  },  {    name: '甄姬',    price: 3888  },  {    name: '马可波罗',    price: 18888  }]
arr2.sort((a, b) => a.price - b.price)

splice

基本用法:对数组进行操作,包括删除,添加,替换等。arr.splice(start, deleteCount,items) 第一个参数(起始位置),第二个参数(删除的项数),第三个参数(插入任意数量的项) 影响: 返回处理后的数组,改变源数组
应用: 数组排序

const arr = [
  {
    name: '李白',
    price: 18888
  },
  {
    name: '妲己',
    price: 5888
  },
  {
    name: '甄姬',
    price: 3888
  },
  {
    name: '马可波罗',
    price: 18888
  }
]
// const arr2 = arr.splice(1, 1) // 在下标为1位置开始删除,删除一个

// const arr3 = arr.splice(1, 0, {
//   name: '王昭君',
//   price: 5888
// }) // 在下标为1位置开始,不删除,直接添加

const arr4 = arr.splice(
  1,
  1,
  {
    name: '王昭君',
    price: 5888
  },
  {
    name: '张飞',
    price: 888
  }
) //在下标为1位置开始先删除,然后在该位置添加

toLocalString toString

基本用法toLocaleString()返回对象的字符串表示,该字符串与执行环境的地区对应;toString()返回对象的字符串表示
影响: 不改变源数组
应用:

const a = 6666
console.log(a.toLocaleString()) // "6,666"
console.log(a.toString())  // "6666"
当数字是三位以上时,会每三位出现一个分隔号;

var c = [1,2,3];
console.log(c.toLocaleString());
//1,2,3
console.log(c.toString());
//1,2,3
数组无区别

var dt = new Date();
console.log(dt.toLocaleString());
// 2023/4/9 17:25:11
console.log(dt.toString());
//Sun Apr 09 2023 17:25:11 GMT+0800

总结

  1. LocaleString()会根据你机器的本地环境来返回字符串,它和toString()返回的值在不同的本地环境下使用的符号可能变化
  2. 使用toString()是保险的方法,它不会因为本地环境(例如国家)改变而改变
  3. 为了返回时间类型的值的话,使用toLocaleString()

最后

差不多已经过完了数组中的常用方法,后面会整理一些常用的数组数据处理以及简单的算法等。