数组的常用方法总结

463 阅读6分钟

增删

增加

unshift 前增

let arr = [1]; 
arr.unshift(2); // [2,1]

push 后增

let arr = [1]; 
// 可以一次push多个值
arr.push(2); // [1,2]

删除

shift 前删

let arr = [1,2,3]; 
arr.shift(); // 1 
console.log(arr); // [2,3]

pop 后删

let arr = [1,2,3]; 
arr.pop(); // 3 
console.log(arr); // [1,2]

splice 替换

splice方法可以用来对js的数组进行删除,添加,替换等操作。主要看第二个参数是什么,如果是0表示增加,如果是大于0的表示删除,如果有第三个参数表示添加或者替换。

  1. 删除功能,第一个参数为第一项位置,第二个参数为要删除几个。用法:array.splice(index,num),返回值为删除内容,array为结果值。

2. 插入功能,第一个参数(插入位置),第二个参数(0),第三个参数(插入的项)。 用法:array.splice(index,0,insertValue),返回值为空数组,array值为最终结果值。

3. 替换功能,第一个参数(起始位置),第二个参数(删除的项数),第三个参数(插入任意数量的项)。 用法:array.splice(index,num,insertValue),返回值为删除内容,array为结果值。

拼接

push

let arr1 = [1, 2]
let arr2 = [3, 4]
arr1.push(arr2)
console.log(arr1) // [1,2,[3,4]]

concat: 返回拼接后的副本,不会改变原数组

let arr1 = [1, 2]
let arr2 = [3, 4]
let arr3 = arr1.concat(arr2)
console.log(arr3) // [1,2,3,4]

查找与过滤

indexOf/lastIndexOf

let arr = [1, 2, 3, 1, 5]
let index = arr.indexOf(1)
console.log(index) // 0

let arr = [1, 2, 3, 2, 1, 2]
let index = arr.lastIndexOf(1)
console.log(index) // 4

返回元素在数组中首次出现的下标,如果找不到,返回 -1

find/findIndex

find()方法用于查找数组中符合条件的第一个元素,如果没有符合条件的元素,则返回undefined。findIndex()则是返回元素的下标。

如果找到第一个元素,就结束查找。

let arr = [1, 2, 3, 4, 5]
let num = arr.find(item => item > 1)
console.log(num) // 2

includes

判断数组中是否存在该元素,参数:查找的值、起始位置,可以替换 ES5 时代的 indexOf 判断方式。

var a = [1, 2, 3];
a.includes(2); // true
a.includes(4); // false

filter

对数组的每一项都运行给定的函数,返回 结果为 ture 的项组成的数组

var words = ["spray", "limit", "elite", "exuberant", "destruction", "present", "happy"];

var longWords = words.filter(function(word){
  return word.length > 6;
});
// ["exuberant", "destruction", "present"]

some/every

  • some: 对数组的每一项都运行给定的函数,任意一项都返回 ture,则返回 true
  • every: 对数组的每一项都运行给定的函数,每一项都返回 ture,则返回 true
// every
function isBigEnough(element, index, array) {
  return element < 10;
}    
[2, 5, 8, 3, 4].every(isBigEnough);   // true

// some
function compare(element, index, array) {
  return element > 10;
}    
[2, 5, 8, 1, 4].some(compare);  // false
[12, 5, 8, 1, 4].some(compare); // true

ES6新增常用方法

Array.from

将类似数组的对象(array-like object)和可遍历(iterable)的对象转为真正的数组。

const bar = ["a", "b", "c"];
Array.from(bar); // ["a", "b", "c"]

Array.from('foo'); // ["f", "o", "o"]

Array.of

用于将一组值,转换为数组。这个方法的主要目的,是弥补数组构造函数 Array() 的不足。因为参数个数的不同,会导致 Array() 的行为有差异。

Array.of(7);       // [7]
Array.of(1, 2, 3); // [1, 2, 3]

entries()、values()、 keys()

const arr = ['a', 'b', 'c'];
for(let v of arr.entries()) {
  console.log(v)
}
// [0, 'a'] [1, 'b'] [2, 'c']

const arr = ['a', 'b', 'c'];
for(let v of arr.values()) {
  console.log(v)
}
//'a' 'b' 'c'

const arr = ['a', 'b', 'c'];
for(let v of arr.keys()) {
  console.log(v)
}
// 0 1 2

sort排序

sort方法可直接调用,不传入任何参数,也可传入一个比较函数作为参数。

不传参数的情况

此方法不传入参数时,会使用默认排序方式。先调用每个元素的toString() 方法,然后按照转换后字符串的 Unicode 编码来进行排序,如:我们可以看到结果不是按顺序大小排列的

[1, 2, 3, 15, 22, 33].sort() // 1, 15, 2, 22, 3, 33

传入函数参数(参数只能是函数)

传入函数参数,可以让调用者按照自己的意愿对元素进行排序。

// 函数参数的实现
function compare(value1, value2) {
  if (value1 < value2) {
    return 1
  }
  if (value1 > value2) {
    return -1
  }
  return 0
}
  • 如果函数返回 1 排序后 value1 会位于 value2 之后
  • 返回 -1 排序后 value1 会在 value2 之前;
  • 返回 0 则说明两个元素相等,排序后位置不会发生变化。

注意:传入的参数函数必须要返回值,像这么写是不行的:

function compare(value1, value2) {
  if (value1 < value2) {
    return 1
  }
}

// 修改为:
function compare(value1, value2) {
  if (value1 < value2) {
    return 1
  }
  return -1
}

若 value1 和 value2 的比较结果是随机的,会出现数组乱序的现象。可以利用这一特性来打乱一个数组。

调用 sort 方法,在排序过程中,每次执行会取得随机浮点数。根据随机数来调整每个元素的位置。最后得到乱序之后的数组。

arr.sort(function(a,b){ 
    return Math.random()>.5 ? -1 : 1;
});

转换

toString

let arr = [1, 2]
let str = arr.toString()
console.log(str) // "1,2"

join

let arr = [1, 2, 3]
let str1 = arr.join('.')
console.log(str1) //"1.2.3"
let str2 = arr.join('$')
console.log(str2) //"1$2$3"

map

返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

var users = [
  {name: "张含韵", "email": "zhang@email.com"},
  {name: "江一燕",   "email": "jiang@email.com"},
  {name: "李小璐",  "email": "li@email.com"}
];
var emails = users.map(function (user) { return user.email; });
//["zhang@email.com", "jiang@email.com", "li@email.com"]

reduce


arr.reduce(function(prev, cur, index){
  ...
  }, init);

var arr = [3,9,4,3,6,0,9];
var sum = arr.reduce(function (prev, cur) {
    return prev + cur;
},0);
  • prev 表示上一次调用回调时的返回值,或者初始值 init;
  • cur 表示当前正在处理的数组元素;
  • index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
  • init 表示初始值,如果没传,那么就是数组的第一项

求数组项最大值,求和

var max = arr.reduce(function(prev, cur) {
  return Math.max(prev, cur)
})

数组去重

var newArr = arr.reduce(function(prev, cur) {
  prev.indexOf(cur) === -1 && prev.push(cur)
  return prev
}, [])

let arr = [1, 2, 3, 4, 4, 1]
let newArr = arr.reduce((pre, cur) => {
  if (!pre.includes(cur)) {
    return pre.concat(cur)
  } else {
    return pre
  }
}, [])
console.log(newArr) // [1, 2, 3, 4]

计算数组中每个元素出现的次数

let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']
let nameNum = names.reduce((pre, cur) => {
  if (cur in pre) {
    pre[cur]++
  } else {
    pre[cur] = 1
  }
  return pre
}, {})
console.log(nameNum) //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}

将二维数组转化为一维

let arr = [
  [0, 1],
  [2, 3],
  [4, 5]
]
let newArr = arr.reduce((pre, cur) => {
  return pre.concat(cur)
}, [])
console.log(newArr) // [0, 1, 2, 3, 4, 5]

用递归进行多维数组的打平,递归有个特点就是要有个返回值:

let arr = [
  [0, 1],
  [2, 3],
  [4, [5, 6, 7]]
]
const newArr = function(arr) {
  return arr.reduce(
    (pre, cur) => pre.concat(Array.isArray(cur) ? newArr(cur) : cur),
    []
  )
}
console.log(newArr(arr)) //[0, 1, 2, 3, 4, 5, 6, 7]

将数组打平,ES6有个新的方法flat:

[1, 2, [3, 4]].flat() // [1, 2, 3, 4]

数组的优劣和操作的时间复杂度

优点:更新查找快,由于数组是线性查存储,所以我们只需要给到我们想要的元素下标,就可以方便的更新元素和查找元素。

缺点:增删慢,还是因为数组的线性存储,举个比较简单的例子,比如说我们的书桌上堆放着一摞书,我想要拿第 5 本,我需要动前 4 本才可以拿到想要的。如果书我想把一本书放在中间位置,同样需要动中间位置之前的所有书才可以。

时间复杂度:由于更新查找的时候只需要提供下标,所以时间复杂度是O(1)。增加和删除的时候需要改动数组中的其他元素,所以时间复杂度是O(n)。