小宋爱睡觉 小宋爱睡觉
首页
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • 计算机网络
  • 浏览器原理
  • 性能优化
  • 设计模式
手写系列
  • 字符串
  • 数组
  • 链表
  • 树
  • 动态规划
  • 排序算法
  • GitHub (opens new window)
  • JueJin (opens new window)
首页
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • 计算机网络
  • 浏览器原理
  • 性能优化
  • 设计模式
手写系列
  • 字符串
  • 数组
  • 链表
  • 树
  • 动态规划
  • 排序算法
  • GitHub (opens new window)
  • JueJin (opens new window)
  • 手写系列
  • Promise
  • 场景应用
  • 数组的方法
    • 数组中改变自身的方法
    • 数组中不改变自身的方法
    • 数组扁平化
    • 数组去重
    • flat
    • push
    • filter
    • map
    • reduce
    • splice
    • indexOf
    • 计算多个区间的交集
    • 求数组的交集、差集、并集、补集
    • 不用for循环快速实现 [1, 2, ...100]
  • 正则表达式相关
  • Vue手写
  • 手写系列
Crucials
2021-11-28

数组的方法

# 数组方法

# 数组中改变自身的方法

基于 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

# 数组中不改变自身的方法

// 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

# 数组扁平化

递归

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

迭代

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

扩展操作符

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

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

es6的flat

let arr = [1, [2, [3, 4]]];
function flatten(arr) {
  return arr.flat(Infinity);
}
1
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

# 数组去重

双层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

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

用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

利用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

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

先用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

性能排序: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

# 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

# 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

# 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

# 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

# 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

# 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

# 计算多个区间的交集

/**
 * 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

# 求数组的交集、差集、并集、补集

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

# 不用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
上次更新: 2022/03/20, 19:40:28
场景应用
正则表达式相关

← 场景应用 正则表达式相关→

Copyright © 2021-2025 粤ICP备2021165371号
  • 跟随系统
  • 浅色模式
  • 深色模式