数组的方法
# 数组方法
# 数组中改变自身的方法
基于 ES6,会改变自身值的方法一共有
9
个,分别为pop、push、reverse、shift、sort、splice、unshift,以及两个 ES6 新增的方法 copyWithin 和 fill
// pop方法
var array = ["cat", "dog", "cow", "chicken", "mouse"];
var item = array.pop();
console.log(array); // ["cat", "dog", "cow", "chicken"]
console.log(item); // mouse
// push方法
var array = ["football", "basketball", "badminton"];
var i = array.push("golfball");
console.log(array);
// ["football", "basketball", "badminton", "golfball"]
console.log(i); // 4
// reverse方法
var array = [1,2,3,4,5];
var array2 = array.reverse();
console.log(array); // [5,4,3,2,1]
console.log(array2===array); // true
// shift方法
var array = [1,2,3,4,5];
var item = array.shift();
console.log(array); // [2,3,4,5]
console.log(item); // 1
// unshift方法
var array = ["red", "green", "blue"];
var length = array.unshift("yellow");
console.log(array); // ["yellow", "red", "green", "blue"]
console.log(length); // 4
// sort方法
var array = ["apple","Boy","Cat","dog"];
var array2 = array.sort();
console.log(array); // ["Boy", "Cat", "apple", "dog"]
console.log(array2 == array); // true
// splice方法
var array = ["apple","boy"];
var splices = array.splice(1,1);
console.log(array); // ["apple"]
console.log(splices); // ["boy"]
// copyWithin方法
var array = [1,2,3,4,5];
var array2 = array.copyWithin(0,3);
console.log(array===array2,array2); // true [4, 5, 3, 4, 5]
// fill方法
var array = [1,2,3,4,5];
var array2 = array.fill(10,0,3);
console.log(array===array2,array2);
// true [10, 10, 10, 4, 5], 可见数组区间[0,3]的元素全部替换为10
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
35
36
37
38
39
40
41
42
43
44
45
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
35
36
37
38
39
40
41
42
43
44
45
# 数组中不改变自身的方法
// concat方法
var array = [1, 2, 3];
var array2 = array.concat(4,[5,6],[7,8,9]);
console.log(array2); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(array); // [1, 2, 3], 可见原数组并未被修改
// join方法
var array = ['We', 'are', 'Chinese'];
console.log(array.join()); // "We,are,Chinese"
console.log(array.join('+')); // "We+are+Chinese"
// slice方法
var array = ["one", "two", "three","four", "five"];
console.log(array.slice()); // ["one", "two", "three","four", "five"]
console.log(array.slice(2,3)); // ["three"]
// toString方法
var array = ['Jan', 'Feb', 'Mar', 'Apr'];
var str = array.toString();
console.log(str); // Jan,Feb,Mar,Apr
// tolocalString方法
var array= [{name:'zz'}, 123, "abc", new Date()];
var str = array.toLocaleString();
console.log(str); // [object Object],123,abc,2016/1/5 下午1:06:23
// indexOf方法
var array = ['abc', 'def', 'ghi','123'];
console.log(array.indexOf('def')); // 1
// includes方法
var array = [-0, 1, 2];
console.log(array.includes(+0)); // true
console.log(array.includes(1)); // true
var array = [NaN];
console.log(array.includes(NaN)); // 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
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
# 数组扁平化
递归
function flatten(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else {
result.push(arr[i]);
}
}
return result;
}
let arr = [1, [2, [3, 4, 5]]];
console.log(flatten(arr));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
迭代
function flatten(arr) {
return arr.reduce((prev, next) => {
return prev.concat(Array.isArray(next) ? flatten(next) : next);
}, []);
}
let arr = [1, [2, [3, 4, 5]]];
console.log(flatten(arr));
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
扩展操作符
function flatten(arr) {
while (arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
let arr = [1, [2, [3, 4, 5]]];
console.log(flatten(arr));
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
split
和toString
function flatten(arr) {
return arr.toString().split(",");
}
let arr = [1, [2, [3, 4, 5]]];
console.log(flatten(arr));
// [ '1', '2', '3', '4', '5' ]
// 有个缺点是全转成字符串
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
es6
的flat
let arr = [1, [2, [3, 4]]];
function flatten(arr) {
return arr.flat(Infinity);
}
1
2
3
4
2
3
4
可选降几层
function flatDeep(arr, d = 1) {
return d > 0
? arr.reduce(
(acc, val) =>
acc.concat(Array.isArray(val) ? flatDeep(val, d - 1) : val),
[]
)
: arr.slice();
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 数组去重
双层
for
循环
function distinct(arr) {
for (let i=0, len=arr.length; i<len; i++) {
for (let j=i+1; j<len; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
// splice 会改变数组长度,所以要将数组长度 len 和下标 j 减一
len--;
j--;
}
}
}
return arr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Array.filter()
加indexOf
function distinct(a, b) {
let arr = a.concat(b);
return arr.filter((item, index)=> {
return arr.indexOf(item) === index
})
}
1
2
3
4
5
6
2
3
4
5
6
用
Set
数据结构
const array = [1, 2, 3, 5, 1, 5, 9, 1, 2, 8];
Array.from(new Set(array)); // [1, 2, 3, 5, 9, 8]
1
2
3
2
3
利用
map
function uniqueArray(arr) {
let map = new Map();
let res = [];
for (let i = 0; i < arr.length; i++) {
if (!map.get(arr[i])) {
res.push(arr[i]);
map.set(arr[i], true);
}
}
return res;
}
const arr = [1, 2, 3, 5, 1, 5, 9, 1, 2, 8];
console.log(uniqueArray(arr));
// [ 1, 2, 3, 5, 9, 8 ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
obj
键值对
function distinct(array) {
var obj = {};
return array.filter((item) =>
obj.hasOwnProperty(typeof item + item)
? false
: (obj[typeof item + item] = true)
);
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
先用
sort
排序,然后用一个指针从第0
位开始,配合while
循环去重:
function unique (arr) {
arr = arr.sort(); // 排序之后的数组
let pointer = 0;
while (arr[pointer]) {
if (arr[pointer] != arr[pointer + 1]) { // 若这一项和下一项不相等则指针往下移
pointer++;
} else { // 否则删除下一项
arr.splice(pointer + 1, 1);
}
}
return arr;
}
var arr = [1,1,2,5,6,3,5,5,6,8,9,8];
console.log(unique(arr))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
性能排序:Set
> map
> Array.sort
+ 一层遍历去重 > filter + indexOf
> double for cycle
# flat
function flat(arr, depth) {
if (!arr || depth <= 0) {
return arr;
}
return arr.reduce((prev, next) => {
return prev.concat(Array.isArray(next) ? flat(next) : next);
}, []);
}
let arr = [1, [2, [3, 4, 5]]];
console.log(flat(arr));
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# push
let arr = [];
Array.prototype._push = function() {
for(let i = 0 ; i < arguments.length ; i++){
this[this.length] = arguments[i] ;
}
return this.length;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# filter
Array.prototype._filter = function(fn) {
if(typeof fn !== 'function') {
console.error('typeError)
}
const res = []
for(let i = 0; i < this.length; i++) {
fn(this[i]) && res.push(this[i])
}
return res
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# map
Array.prototype._map = function (cb, context) {
const arr = Array.prototype.slice.call(this);
const res = [];
for (let i = 0; i < arr.length; i++) {
res.push(cb.call(context, arr[i], i, this));
}
return res;
};
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# reduce
Array.prototype.myreduce = function(fn, initVal) {
let result = initVal,
i = 0;
if(typeof initVal === 'undefined'){
result = this[i]
i++;
}
while( i < this.length ){
result = fn(result, this[i])
}
return result
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# splice
Array.prototype._splice = function (start, deleteCount) {
// 入参元素个数
let argumentsLen = arguments.length;
// 数组
let array = Object(this);
// 数组长度
let len = array.length;
// 添加元素个数
let addCount = argumentsLen > 2 ? argumentsLen - 2 : 0;
// 计算有效的 start
let startIndex = computeSpliceStartIndex(start, array);
// 计算有效的 deleteCount
let delCount = computeSpliceDeleteCount(startIndex, deleteCount, len);
// 记录删除的数组元素
let deletedElements = new Array(delCount);
// 将待删除元素记录到 deletedArray
recordDeleteElements(startIndex, delCount, array, deletedElements);
// 密封对象
if (delCount !== addCount && Object.isSealed(array)) {
throw new TypeError("the array is sealed");
}
// 冻结对象
if (delCount > 0 && addCount > 0 && Object.isFrozen(array)) {
throw new TypeError("the array is frozen");
}
// 移动数组元素
moveElements(startIndex, delCount, array, addCount);
let i = startIndex;
let argumentsIndex = 2;
// 插入新元素
while (argumentsIndex < argumentsLen) {
array[i++] = arguments[argumentsIndex++];
}
array.length = len - delCount + addCount;
// 返回删除元素数组
return deletedElements;
};
// 计算真实的 start
function computeSpliceStartIndex(start, len) {
// 处理负值,如果负数的绝对值大于数组的长度,则表示开始位置为第0位
if (start < 0) {
start += len;
return start < 0 ? 0 : start;
}
// 处理超出边界问题
return start > len - 1 ? len - 1 : start;
}
// 计算真实的 deleteCount
function computeSpliceDeleteCount(startIndex, deleteCount, len) {
// 超出边界问题
if (deleteCount > len - startIndex) deleteCount = len - startIndex;
// 负值问题
if (deleteCount < 0) deleteCount = 0;
return deleteCount;
}
// 记录删除元素,用于 Array.prototype.splice() 返回
function recordDeleteElements(startIndex, delCount, array, deletedElementd) {
for (let i = 0; i < delCount; i++) {
deletedElementd[i] = array[startIndex + i];
}
}
// 移动数组元素,便于插入新元素
function moveElements(startIndex, delCount, array, addCount) {
let over = addCount - delCount;
if (over) {
// 向后移
for (let i = array.length - 1; i >= startIndex + delCount; i--) {
array[i + over] = array[i];
}
} else if (over < 0) {
// 向前移
for (let i = startIndex + delCount; i <= array.length - 1; i++) {
if (i + Math.abs(over) > array.length - 1) {
// 删除冗于元素
delete array[i];
continue;
}
array[i] = array[i + Math.abs(over)];
}
}
}
const months = ["Jan", "March", "April", "June"];
console.log(months._splice(1, 0, "Feb"));
// []
console.log(months);
// ["Jan", "Feb", "March", "April", "June"]
console.log(months._splice(4, 1, "May"));
// ["June"]
console.log(months);
// ["Jan", "Feb", "March", "April", "May"]
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# indexOf
// String.prototype.indexOf()
function sIndexOf(str, searchStr, fromIndex = 0){
var regex = new RegExp(`${searchStr}`, 'ig')
regex.lastIndex = fromIndex
var result = regex.exec(str)
return result ? result.index : -1
}
// 测试
var paragraph = 'The quick brown fox jumps over the lazy dog. If the dog barked, was it really lazy?'
var searchTerm = 'dog'
// 测试一:不设置 fromIndex
console.log(sIndexOf(paragraph, searchTerm))
// 40
console.log(paragraph.indexOf(searchTerm));
// 40
// 测试二:设置 fromIndex
console.log(sIndexOf(paragraph, searchTerm, 41))
// 52
console.log(paragraph.indexOf(searchTerm, 41));
// 52
// Array.prototype.indexOf()
function aIndexOf(arr, elem, fromIndex = 0){
if(!elem) return -1
for(let i = fromIndex; i < arr.length; i++) {
if(arr[i] === elem) return i
}
return -1
}
// 测试
var beasts = ['ant', 'bison', 'camel', 'duck', 'bison']
// 测试一:不设置 fromIndex
console.log(aIndexOf(beasts, 'bison'))
// 1
console.log(beasts.indexOf('bison'))
// 1
// 测试二:设置 fromIndex
console.log(aIndexOf(beasts, 'bison', 2))
// 4
console.log(beasts.indexOf('bison', 2))
// 4
function indexOf(items, item, fromIndex = 0) {
let isArray = Array.isArray(items);
let isString = Object.prototype.toString.call(items) == '[object String]';
if (!isArray && !isString) throw new SyntaxError();
if(isArray) return sIndexOf(items, item, fromIndex)
else return aIndexOf(items, item, fromIndex)
}
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 计算多个区间的交集
/**
* 1.计算多个区间的交集
* 区间用长度为2的数字数组表示,如[2, 5]表示区间2到5(包括2和5);
* 区间不限定方向,如[5, 2]等同于[2, 5];
* 实现`getIntersection 函数`
* 可接收多个区间,并返回所有区间的交集(用区间表示),如空集用null表示
* 示例:
* getIntersection([5, 2], [4, 9], [3, 6]); // [4, 5]
* getIntersection([1, 7], [8, 9]); // null
*/
function getIntersection(...arr) {
if (!arr || !arr.length) return null;
// 对数组排序
arr.forEach((item) => {
item.sort((a, b) => a - b);
});
// 对数组的数组排序
arr.sort((a, b) => a[0] - b[0]);
const res = [...arr[0]];
for (let i = 1; i < arr.length; i++) {
// 第i个区间的左边已经大于并集的右边(最小的比最大的还大)
if (res[1] < arr[i][0]) return null;
if (res[0] <= arr[i][0]) {
res[0] = Math.max(res[0], arr[i][0]);
res[1] = Math.min(res[1], arr[i][1]);
}
}
return res;
}
console.log(getIntersection([5, 2], [4, 9], [3, 6]));
console.log(getIntersection([1, 7], [8, 9]));
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
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
# 求数组的交集、差集、并集、补集
const a = [1, 2, 3, 4, 5];
const b = [2, 4, 6, 8, 10];
//交集
const c = a.filter((v) => b.indexOf(v) > -1);
//差集
const d = a.filter((v) => b.indexOf(v) == -1);
//补集
const e = a
.filter((v) => b.indexOf(v) === -1)
.concat(b.filter((v) => a.indexOf(v) === -1));
//并集
const f = a.concat(b.filter((v) => a.indexOf(v) === -1));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 不用for
循环快速实现 [1, 2, ...100]
//1.
new Array(100).fill(1).map((v,k)=>k+1)
//2.
Array.from(new Array(100), (v,k) => k+1)
1
2
3
4
5
2
3
4
5
上次更新: 2022/03/20, 19:40:28