关于数组的一些操作

记录一下常见的关于数组的操作

1、 数组降维(数组扁平化)

1.1 flat

直接上大招

flat()是es6提供的一个新的关于数组的方法,该方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

在mdn查看更多关于flat的介绍

1.2 其他一些骚操作

1
2
3
4
5
6
7
var arr = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
// some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true
// arr.some(Array.isArray)相当于arr.some((item, index) => Array.isArray(item, index))
while (arr.some(Array.isArray)) {
arr = [].concat(...arr)
}
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

2、 数组去重

2.1 一维数组去重

2.1.1 Set

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。可以利用这个特性去重。

1
2
3
var arr = [1, 3, 1, 2, 3, 4, 55, 23, 4, 23, 2];
var aaa = new Set(arr)
console.log([...aaa]) //  [1, 3, 2, 4, 55, 23]

封装一下

1
2
3
4
5
6
// Array.from 方法可以将 Set 结构转为数组。
const a = [1, 3, 1, 2, 3, 4, 55, 23, 4, 23, 2];
function unique(array) {
return Array.from(new Set(array));
}
console.log(unique(a)) // [1, 3, 2, 4, 55, 23]
2.1.2 filter

第一种写法

1
2
3
4
5
6
var arr = [1, 3, 1, 2, 3, 4, 55, 23, 4, 23, 2];
// filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
// arr.indexOf 返回在数组中可以找到一个给定元素的第一个索引
// 这个方法的原理是:如果给定元素首次出现的索引不等于他自身的索引则剔除
var aaa = arr.filter((item, index) => arr.indexOf(item) === index);
console.log(aaa) // [1, 3, 2, 4, 55, 23]

第二种写法

1
2
3
const a = [1, 3, 1, 2, 3, 4, 55, 23, 4, 23, 2];
const b = a.filter((item, index, self) => self.indexOf(item) === index)
console.log(b) //[1, 3, 4, 5, 2, 6, 7, 8]
2.1.3 reduce

这段代码有丶骚没看懂,先收藏

1
2
3
var arr = [1, 3, 1, 2, 3, 4, 55, 23, 4, 23, 2];
var aaa = arr.reduce((unique, item) => unique.includes(item) ? unique : [...unique, item], [])
console.log(aaa) // [1, 3, 2, 4, 55, 23]
2.1.4 来几个es5版本的数组去重
1
2
3
4
5
6
7
8
9
10
11
12
// 利用indexOf
var arr = [1, 3, 1, 2, 3, 4, 55, 23, 4, 23, 2];
function unique(arr) {
var result = [];
for (let i = 0; i < arr.length; i++) {
if (arr.indexOf(arr[i]) === -1) {
result.push(arr[i])
}
}
return result;
}
console.log(unique(arr)) // [1, 4, 55, 23, 4, 23, 2]
2.1.5 Map结合filter
1
2
3
4
function arrayUnique(array) {
var map = new Map();
return array.filter((item) => !map.has(item) && map.set(item, 1));
}

2.2 数组对象去重

数组对象去重

3、 打乱数组

打乱数组

4、 数组排序

4.0 一些排序算法

使用算法进行的数组排序

4.1 sort函数

sort() 方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的

不传任何函数默认是按UTF-16排序

1
2
3
4
const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]

5、 数组遍历

5.1 Array.from()

在mdn查看更多关于Array.from的介绍

1
2
3
4
var arr = [1, 2, 3];
Array.from(arr, (item) => {
console.log(item) // 1,2,3
});

6、 数组交集 并集 差集

交集意味着找出两个集合中都有的元素。
并集意味着将集合合并。
差集意味着将从一个集合中剔除出现在另一个集合中的元素。

6.1 交集

es5

1
2
3
4
let arr1 = [1, 2, 3, 5, 8, 9]
let arr2 = [1, 3, 5, 7]
let arr = arr1.filter(item => arr2.includes(item))
console.log(arr) // 1,3,5

es6

1
2
3
4
let arr1 = [1, 2, 3, 5, 8, 9]
let arr2 = [1, 3, 5, 7]
var intersection = arr1.filter(item => new Set(arr2).has(item))
console.log(intersection); // 1,3,5

6.2 并集

es5

1
2
3
4
let arr1 = [1, 2, 3, 5, 8, 9]
let arr2 = [1, 3, 5, 7]
let ans = arr1.concat(arr2.filter(item => arr1.indexOf(item) === -1))
console.log(ans); // [1, 2, 3, 5, 8, 9, 7]

es6

1
2
3
4
let arr1 = [1, 2, 3, 5, 8, 9]
let arr2 = [1, 3, 5, 7]
let ans = Array.from(new Set([...arr1, ...arr2]))
console.log(ans); // [1, 2, 3, 5, 8, 9, 7]

6.3 差集

arr1中有而arr2没有的

es5

1
2
3
4
let arr1 = [1, 2, 3, 5, 8, 9]
let arr2 = [1, 3, 5, 7]
let ans = arr1.filter(item => arr2.indexOf(item) === -1)
console.log(ans); // [2, 8, 9]

7、 对比两个数组是否相同

使用第三方库

例如lodash,不仅可以比较数组,对象也可以

1
2
3
4
5
//   var object = { a: 1 };
// var other = { a: 1 };
var object = [1, 2, 3];
var other = [1, 2, 3];
console.log(_.isEqual(object, other)); // true

一些hack方法

1
2
3
4
var a1 = [1, 2, 3];
var a2 = [1, 2, 3];

console.log(JSON.stringify(a1) == JSON.stringify(a2)); // Returns true
1
2
3
4
5
6
7
8
var array1 = [4, 8, 9, 10];
var array2 = [4, 8, 9, 10];

var is_same =
array1.length == array2.length &&
array1.every((element, index) => element === array2[index]);

console.log(is_same); // true

正规军

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function isEqual(array, array1) {
// 如果是假值则返回false
if (!array || !array1) {
return false;
}
// 比较长度,可以节省大量时间
if (array.length != array1.length) {
return false;
}
for (let i = 0; i < array.length; i++) {
// 检查是否为嵌套数组
if (array[i] instanceof Array && array1[i] instanceof Array) {
// 递归判断
if (!isEqual(array[i], array1[i])) {
return false;
}
} else if (array[i] !== array1[i]) {
return false;
}
}
return true;
}

const arr = [1, 2, 3];
const arr1 = [1, 2, 3];
console.log(isEqual(arr, arr1)); // true

当然我们也可以挂载到Array的原型上,这样使用起来更加方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Warn if overriding existing method
if (Array.prototype.equals)
console.warn(
"Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code."
);
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array) return false;

// compare lengths - can save a lot of time
if (this.length != array.length) return false;

for (var i = 0, l = this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i])) return false;
} else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
};
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", { enumerable: false });

console.log([1, 2, 3].equals([1, 2, 3, 4])); // false
console.log([1, 2, 3].equals([1, 2, 3])); // true

拓展题:对比两个对象是否相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var obj = { name: 1, age: 18, Hobby: [1, 2, 3] };
var obj1 = { name: 1, age: 18, Hobby: [1, 2, 3] };

function deepEqual(object, object1) {
// 指向同一内存时
if (object === object1) {
return true;
}
const key = Object.keys(object);
const key1 = Object.keys(object1);
if (key.length !== key1.length) {
return false;
}
for (const _key of key) {
const val = object[_key];
const val1 = object1[_key];
// 检查对象子元素中是否还有嵌套的对象
const isAllObject = isObject(val) && isObject(val1);
// 有嵌套元素,但是不相等
if (isAllObject && !deepEqual(val, val1)) {
return false;
}
if (!isAllObject && val !== val1) {
return false;
}
}
return true;
}

function isObject(obj) {
return typeof obj === "object" && obj !== null;
}

console.log(deepEqual(obj, obj1)); // true

再次拓展:对比两个数组对象是否相同

我们可以借用上面定义的deepEqual方法

1
2
3
function arraysEqual(a1, a2) {
return a1.length === a2.length && a1.every((item, index) => deepEqual(item, a2[index]));
}

8、 创建包含0-10数字数组

1
2
3
Array.from(Array(10).keys())

[...Array(10).keys()]

参考资料

How to compare arrays in JavaScript?


关于数组的一些操作
https://xypecho.github.io/2019/12/04/关于数组的一些操作/
作者
很青的青蛙
发布于
2019年12月4日
许可协议