Javascript 数组常用算法

271 阅读5分钟

汇总

  1. pop() 删除数组的最后一项并返回删除的元素
  2. push() 往数组的最后添加元素并返回数组的长度
  3. shift() 删除数组的第一项并返回删除元素
  4. unshift() 往数组的第一项添加元素并返回数组的长度
  5. slice() 截取数组的区间长度
  6. splice(1)截取数组的长度 splice(1,2) 从小标 1 元素开始删除,删除两个元素 splice(1,0,'a') 替换元素
  7. concat() 合并元素
  8. split('') 把字符串变成数组
  9. join() 把数组元素合成字符串
  10. trim()去除字符串左右两边的空格
  11. sort() 排列大小写的顺序,数字的大小
  12. reverse() 将字符串或数组进行倒叙
  13. some() 循环数组中如果有一个是 true 就返回一个 true
  14. every() 必须是全部元素都满足添加 true 才返回 true 要不然其中不一个不满足就返回 false
  15. forEach() 不返回任何值
  16. filter() 只返回满足条件的元素
  17. map() 返回元素操作后的值
  18. reduce(sum,i,[]) 进行元素的累加,第一个参数是存储变量,第二个参数元素,第三个元素是初始值
  19. for in 可以遍历原型链上的元素,但是性能较差,遍历对象的话返回的是键名,遍历数组返回的是下标
  20. for of 不可以遍历对象,遍历数组的话返回的是值
  21. indexOf() 查找元素,找打的话就返回元素的下标,没找到的话就返回 -1
  22. includes() 判断是否包含目标元素,找到的就返回 true,没找到就返回 false
  23. find() 查找元素,如果有的话就返回第一个元素
  24. toString() 把数组变成字符串
  25. replice(匹配元素,要替换的元素)
Array.prototype.myUcase = function () {
  for (i = 0; i < arr.length; i++) {
    arr[i] = arr[i].toUpperCase();
  }
};

增删改查方法

concat()

合并两个数组 - concat()

var hege = ["Cecilie", "Lone"];
var stale = ["Emil", "Tobias", "Linus"];
var children = hege.concat(stale); // Cecilie,Lone,Emil,Tobias,Linus

合并三个数组 - concat()

var parents = ["A", "B"];
var brothers = ["C", "D", "E"];
var children = ["F", "G"];
var family = parents.concat(brothers, children); // A,B,C,D,E,F,G

pop()

删除数组的最后一个元素 - pop(),并返回删除的元素

let arr = ["h", "e", "l", "l", "o"];
console.log(arr.pop()); // o
console.log(arr); // ['h','e','l','l']

push()

在数组的最后添加一个元素 - push(),并返回数组的长度

let arr = ["h", "e", "l", "l", "o"];
console.log(arr.push("1")); // 6
console.log(arr); // ['h', 'e', 'l', 'l', 'o', '1']

shift()

删除数组的第一个元素

let arr = ["h", "e", "l", "l", "o"];
console.log(arr.shift()); // h
console.log(arr); // ['e', 'l', 'l', 'o', '1']

unshift()

在数组的头部添加元素 unshift

let arr = ["h", "e", "l", "l", "o"];
console.log(arr.unshift("A")); // 6
console.log(arr); // ['A', 'h', 'e', 'l', 'l', 'o']

slice()

从一个数组中截取元素 slice(), 不会改变原数组

let arr = ["h", "e", "l", "l", "o"];
console.log(arr.slice(1, 2)); // ['e']
console.log(arr); // ['h', 'e', 'l', 'l', 'o']

splice()

在数组的第 2 个位置添加一个元素 splice()

let arr = ["h", "e", "l", "l", "o"];
console.log(arr.splice(1, 2)); // ['e']
console.log(arr); // ['h', 'e', 'l', 'l', 'o']

let arr = ["h", "e", "l", "l", "o"];
console.log(arr.splice(1, 0, "A")); // []  arr: ['h', 'A', 'e', 'l', 'l', 'o']
console.log(arr.splice(1, 1, "A")); // ['e']  arr: ['h', 'A', 'l', 'l', 'o']
console.log(arr.splice(1, 2, "A")); //  ['e', 'l']   arr: ['h', 'A', 'l', 'o']
arr.splice(1, 1); // ["h", "l", "l", "o"]
arr.splice(1, 2); // ["h", "l", "o"] 从下标 [1] 开始删除2个元素
arr.splice(3); // ['h', 'e', 'l'] 保留前3个元素

charAt()

返回给定索引位置的字符,由传给方法的整数参数指定 charAt()

let message = "abcde";
console.log(message.charAt(2)); // "c"

排序方法

reverse()

将一个数组中的元素顺序反转排序

let arr = ["h", "e", "l", "l", "o"];
console.log(arr.reverse()); // ['o', 'l', 'l', 'e', 'h']
console.log(arr); // ['o', 'l', 'l', 'e', 'h']

sort()

let num = [1, 5, 3, 8, 0];
function myNum(num1, num2) {
  if (num1 < num2) {
    return -1;
  } else if (num1 > num2) {
    return 1;
  } else {
    return 0;
  }
}
console.log(num.sort(myNum)); // [0, 1, 3, 5, 8]

转换方法

toString()

转换数组到字符串

let arr = ["h", "e", "l", "l", "o"];
console.log(arr.toString()); // h,e,l,l,o

把字符串按照指定的分割符,拆分成数组中的每一项 split

let str = "12+23+34";
console.log(str.split()); // ['12+23+34']
console.log(str.split("+"));// [12,23,34]
console.log(str.split("")); //   ['1', '2', '+', '2', '3', '+', '3', '4']

join()

用数组的元素组成字符串 - join()

let arr = ["h", "e", "l", "l", "o"];
let str = arr.join("");
console.log(str); // hello

replice()

接受两个参数,第一个参数为匹配的内容,第二个元素为替换的元素(可用函数)

let str = "hello";
console.log(str.replice("l", "A")); // heAlo

trim()、trimLeft()、trimRight()

repeat()

接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果

let stringValue = "na ";
let copyResult = stringValue.repeat(2); // na na

toLowerCase()、 toUpperCase()

大小写转化

let stringValue = "hello world";
console.log(stringValue.toUpperCase()); // "HELLO WORLD"
console.log(stringValue.toLowerCase()); // "hello world"

遍历方法

some() every()

forEach() filter() map() 五者都不会改变原数组

some()

对数组每一项都运行传入的函数,如果有一项函数返回 true,则这个方法返回 true

let arr = ["h", "e", "l", "l", "o"];
let a = arr.some((item) => item === "l");
console.log(a); // true

every()

对数组每一项都运行传入的函数,如果有一项函数返回 false,则这个方法返回 true

let arr = ["h", "e", "l", "l", "o"];
let a = arr.some((item) => item === "l");
console.log(a); // false

find()

找到匹配的第一个元素

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

forEach()

forEach() 对数组的每一项都进行循环操作,但是不会有任何返回值 如果只是进行循环不需要返回值的话就可以用 forEach()

let arr = [1, 2, 3, 4, 5];
let a = arr.forEach((item) => item > 4);
console.log(a); // 没有返回值 undefined
console.log(arr); // [1, 2, 3, 4, 5]

filter()

filter() 对数组的每一项都进行循环操作,满足条件的返回当前元素,并不是返回操作后的值 如果是过滤筛选的相对应的元素的话就可以使用 filter()

let arr = [1, 2, 3, 4, 5];
let a = arr.filter((item) => item > 3);
console.log(a); // [4,5]
console.log(arr); // [ 4, 5]

let arr = [1, 2, 3, 4, 5];
let a = arr.filter((item) => item * 3);
console.log(a); // [1, 2, 3, 4, 5]
console.log(arr); // [1, 2, 3, 4, 5]

map()

map() 对数组的每一项都进行循环操作,返回操作后的元素,并不是返回当前元素

let arr = [1, 2, 3, "a", 4, 5];
let a = arr.map((item) => item * 2);
console.log(a); // [2, 4, 6, NaN, 8, 10]
console.log(arr); // [1, 2, 3, 'a', 4, 5]

for in for of

for in 可以遍历整个原型链,性能非常差不推荐使用,遍历对象返回的是键名,遍历数组返回的是下标 for of 只遍历当前对象,不会遍历原型链,遍历数组返回的是值

let obj = {
  name: "小王",
  age: 21,
};

let arr = ["h", "e", "l", "l", "o"];

for (const key in obj) {
  console.log(key); // name age
}

for (const key in arr) {
  console.log(key); // 0 1 2 3 4
}

for (const key of obj) {
  console.log(key); // obj 是不可迭代的
}

for (const key of arr) {
  console.log(key); // h e l l o
}

数组去重

Array.from 与 set 去重 Array.from 方法可以将 Set 结构转换为数组结果,而我们知道 set 结果是不重复的数据集,因此能够达到去重的目的

let arr = [1, 1, 2, 2, 3, 3];
function unique(arr) {
  if (!Array.isArray(arr)) return;
  return Array.from(new Set(arr));
}
console.log(unique(arr)); // [1, 2, 3]

let arr = [1, 1, 2, 2, 3, 3];
function unique(arr) {
  if (!Array.isArray(arr)) return;
  let arr1 = [];
  arr.forEach((key) => {
    // if (!arr1.includes(key)) arr1.push(key)
    if (arr1.indexOf(key) === -1) arr1.push(key);
  });
  // return [...new Set(arr)]
  return arr1;
}
console.log(unique(arr)); // // [1, 2, 3]
let arr = [
  { id: 1, name: "张三" },
  { id: 2, name: "李四" },
  { id: 11, name: "王五" },
  { id: 1, name: "张三" },
  { id: 11, name: "王五" },
  { id: 3, name: "李四" },
];

function unique(arr) {
  let newArr = [];
  arr.forEach((item) => {
    if (!newArr.find((key) => key.id === item.id)) newArr.push(item);
  });
  return newArr;
}
console.log(unique(arr));
// 0: {id: 1, name: '张三'}
// 1: {id: 2, name: '李四'}
// 2: {id: 11, name: '王五'}
// 3: {id: 3, name: '李四'}

验证括号是否合法

这是一个很巧妙的用法,我在 dev.to 上看到的用法。如果结果等于 0 说明,括号数量是合法的。

[..."(())()(()())"].reduce((a, i) => (i === "(" ? a + 1 : a - 1), 0);
// 输出:0

// 使用循环方式
let status = 0;
for (let i of [..."(())()(()())"]) {
  if (i === "(") status = status + 1;
  else if (i === ")") status = status - 1;
  if (status < 0) {
    break;
  }
}

按属性分组

let obj = [
  { name: "张三", job: "数据分析师", country: "中国" },
  { name: "艾斯", job: "科学家", country: "中国" },
  { name: "雷尔", job: "科学家", country: "美国" },
  { name: "鲍勃", job: "软件工程师", country: "印度" },
];

let a = obj.reduce((total, item) => {
  // 如果没有标题的时候就添加一个标题
  if (!total[item.country]) total[item.country] = [];
  // 有的话就往后添加
  total[item.country].push(item);
  return total;
}, []); // [] 是 total 的数据类型
console.log(a); // [中国: Array(2), 美国: Array(1), 印度: Array(1)]

数组扁平化

这里展示的数组只有一级深度,如果数组是多级可以使用递归来进行处理

当然也可以使用 ES6 的.flat 方法替代

let arr = [
  [3, 4, 5],
  [2, 5, 3],
  [4, 5, 6],
];
console.log(arr.flat()); //  [3, 4, 5, 2, 5, 3, 4, 5, 6]

let a = arr.reduce((total, item) => total.concat(item), []);
console.log(a); //  [3, 4, 5, 2, 5, 3, 4, 5, 6]

反转字符

let str = "hello world";
let a = [...str].reduce((total, item) => item + total);
let a = [...str].reverse().join("");
console.log(a); // dlrow olleh