前端系列第10期-js数组骚操作

前言

本文主要从应用讲一些数组api的骚操作,如一行代码就实现扁平化n维数组、数组去重、求数组最大值、数组求和、排序、对象和数组的转化等。

扁平化n维数组

一行代码实现

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

Array.flat(n)是ES10扁平数组的api,n表示维度,n值为Infinity时维度为无限大。

一般方式实现

1
2
3
4
5
6
7
8
function flatten(arr) {
while(arr.some(item=>Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
flatten([1,[2,3]]) // [1,2,3]
flatten([1,[2,3,[4,5]]]) // [1,2,3,4,5]

实质是利用递归和数组合并的方式concat实现扁平。

数组元素去重

一行代码实现

1
2
Array.from(new Set([1,2,3,3,4,4])) // [1,2,3,4]
[...new Set([1,2,3,3,4,4])] // [1,2,3,4]

Set是ES6新出来的一种定义不重复数组的数据类型。
Array.from是将类数组转化为数组。
...是扩展运算符,将Set里面的值转化为字符串。

一般方式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Array.prototype.distinct = function () {
let arr = this,
result = [],
i,
j,
len = arr.length;
for(i=0; i<len; i++) {
for(j=i+1; j<len; j++) {
if(arr[i] === arr[j]) {
j = ++i;
}
}
result.push(arr[i]);
}
return result;
}
[1,2,3,3,4,4].distinct(); // [1,2,3,4]

实质是新建立一个数组存值,循环两个数组值相比较。

数组排序

一行代码实现

1
2
[1,2,3,4].sort() // [1,2,3,4] 默认升序
[1,2,3,4].sort((a, b) => b - a) // [4,3,2,1] 降序

sort是js内置的排序方法,参数为一个函数

一般方法实现

冒泡排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Array.prototype.bubleSort = function () {
let arr = this,
len = arr.length;
for(let outer=len; outer>= 2; outer--) {
for(let inner=0; inner<=outer-1; inner++) {
if(arr[inner] > arr[inner+1]) {
// 升序
[arr[inner], arr[inner+1]] = [arr[inner+1], arr[inner]];
}
}
}
return arr;
}
[1,3,2,4].bubleSort() // [1,2,3,4]

选择排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
Array.prototype.selectSort = function () {
let arr = this;
len = arr.length;
for(let i=0; i<len; i++) {
for(let j=i; j<len; j++) {
if(arr[i] > arr[j]) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
}
return arr;
}
[1,2,3,4].selectSort(); // [1,2,3,4]

寻找数组最大值

一行代码实现

1
2
3
4
5
Math.max(...[1,2,3,4]) // 4
Math.max.apply(this, [1,2,3,4]) // 4
[1,2,3,4].reduce((prev, cur, curIndex, arr)=> {
return Math.max(prev, cur);
}, 0) // 4

Math.max()Math对象内置的方法,参数是字符串。
reduce是ES5的数组的api,参数有函数和默认初始值。
函数有四个参数:

  • pre: 上一次的返回值
  • cur: 当前值
  • curIndex: 当前索引值
  • arr: 当前数组

一般方式实现

先排序再取值。

数组求和

一行代码实现

1
2
3
[1,2,3,4].reduce(function (prev, cur) {
return prev + cur;
}, 0) // 10

一般方式实现

1
2
3
4
5
6
7
8
9
10
11
function sum(arr) {
let len = arr.length;
if(len == 0) {
return 0;
} else if (len == 1) {
return arr[0];
} else {
return arr[0] + sum(arr.slice(1));
}
}
sum([1,2,3,4]) // 10

利用slice截取改变数组,再利用递归求和,当然迭代更好。

数组合并

一行代码实现

1
2
3
[1,2,3,4].concat([5,6]) // [1,2,3,4,5,6]
[...[1,2,3,4],...[5,6]] // [1,2,3,4,5,6]
[1,2,3,4].push.apply([1,2,3,4],[5,6]) // [1,2,3,4,5,6]

一般方式实现

1
2
3
[5,6].map(item => {
[1,2,3,4].push(item)
}) // [1,2,3,4,5,6]

数组判断是否包含值

一行代码实现

1
2
3
4
[1,2,3].includes(4) // false
[1,2,3].indexOf(4) // -1 若存在返回索引
[1,2,3].find((item) => item ===3) // 3 若不存在返回undefined
[1,2,3].findIndex((item) => item ===3) // 2 若不存在返回-1

includes()find()findIndex()是ES6的api。

一般方式实现

1
2
3
[1,2,3].some(item => {
return item === 3
}); // true

类数组转化

一行代码实现

1
2
3
4
Array.prototype.slice.call(arguments)
Array.prototype.slice.apply(arguments)
Array.from(arguments)
[...arguments]

类数组: 表示有length属性,但是不具备数组的方法。
callapply: 改变slice里面的this指向arguments,所以arguments也可以调用数组的方法。
...: 将类数组扩展为字符串,再定义为数组。

一般方式实现

1
2
3
4
5
6
7
8
9
Array.prototype.slice = function (start, end) {
let result = new Array();
start = start || 0;
end = end || this.length;
for(let i=start; i<end; i++) {
result.push(this[i]);
}
return result;
}

数组每一项设置值

一行代码实现

1
[1,2,3].fill(false) // [false, false, false]

fill是ES6的方法。

一般方式实现

1
[1,2,3].map(()=> 0)

数组每一项是否满足条件

一行代码实现

1
[1,2,3].every(item => {return item>2}) // false

every是ES5的api,每一项满足返回true

数组有一项满足条件

1
[1,2,3].some(item => {return item>2}) // true

some是ES5的api,有一项满足返回true

过滤数组

一行代码实现

1
[1,2,3].filter(item => {return item>2}) // [3]

filter是ES5的api,返回满足条件的元素数组。

对象和数组转化

一行代码实现

1
2
3
4
Object.keys({name: "张三", age: 14}) // ['name', 'age']
Object.values({name: "张三", age: 14}) // ['张三', 14]
Object.entries({name: "张三", age: 14}) // [[name, "张三"], [age, 14]]
Object.fromEntries([name, "张三"], [age, 14]) // ES10的api {name: "张三", age: 14}