数组的一些操作技巧


判断数组是否包含某个值

let arr = ['a', 'b', 'c'];
console.log(arr.includes('d'));
// false
console.log(arr.includes('b'));
// true
  • 延申:判断字符串是否包含其他字符串
    let str = '判断字符串是否包含其他字符串'
    str.startsWith("判断")         // true
    str.endsWith("666")           // false
    str.includes("是否")       // true
    str.includes("复制")       // false

快速复制数组

const arr = [1, 2, 3, 4];
const sameArr = [...arr];
console.log("arr: ", arr, "\n", "sameArr: ", sameArr);

// arr:[1, 2, 3, 4]
// sameArr:[1, 2, 3, 4]

快速合并数组

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];
const mergedArr = [...arr1, ...arr2, ...arr3];
console.log("mergedArr: ", mergedArr);

// mergedArr:[1, 2, 3, 4, 5, 6, 7, 8, 9]

new Set 数组合并去重

const arr1 = [1, 2, 3];
const arr2 = [3, 2, 1];
const arr3 = [7, 8, 9];
const mergedArr = Array.from(new Set([...arr1, ...arr2, ...arr3]))
console.log("mergedArr: ", mergedArr);

// mergedArr:[1, 2, 3, 7, 8, 9]

new Set 数组对象去重

const arr1 = [
  { name: "张三", age: 18, address: "北京" },
  { name: "李四", age: 20, address: "天津" },
  { name: "张三", age: 18, address: "北京" },
];
const stringsArr1 = arr1.map((item) => JSON.stringify(item)) // 1、转化成string类型
const removeDupList = Array.from(new Set(stringsArr1))  // 2、转化为真正的数组
const mergedArr = removeDupList.map((item) => JSON.parse(item)) // 3、字符串类型转化为对象类型
console.log("mergedArr: ", mergedArr);
// mergedArr: [{ name: "张三", age: 18, address: "北京" },{ name: "李四", age: 20, address: "天津" }]

快速过滤掉相同元素

const arr = [1, 1, 2, 3, 4, 5, 5, 2, 8, 9, 6];
const uniqueArr = [...new Set(arr)];
console.log("uniqueArr: ", uniqueArr);

// uniqueArr: [1, 2, 3, 4, 5, 8, 9, 6]

Tips

  • ES6 之 new Set()

    • Set 是 es6 新增的数据结构,似于数组,但它的一大特性就是所有元素都是唯一的,没有重复的值,我们一般称为集合。
      • Set 对象方法
      • add 添加某个值,返回 Set 对象本身
      • clear 删除所有的键/值对,没有返回值
      • delete 删除某个键,返回 true,如果删除失败,返回 false
      • forEach 对每个元素执行指定操作
      • has 返回一个布尔值,表示某个键是否在当前 Set 对象之中
        // Array 转 Set
        var mySet = new Set(["value1", "value2", "value3"]);
        // 用...操作符,将 Set 转 Array
        var myArray = [...mySet];
        // String 转 Set
        var mySet = new Set("hello"); // Set(4) {"h", "e", "l", "o"}
        // 注:Set 中 toString 方法是不能将 Set 转换成 String
        Set 对象作用
        // 数组去重
        var mySet = new Set([1, 2, 3, 4, 4]);
        [...mySet]; // [1, 2, 3, 4]
        
        // 并集
        var a = new Set([1, 2, 3]);
        var b = new Set([4, 3, 2]);
        var union = new Set([...a, ...b]); // {1, 2, 3, 4}
        
        // 交集
        var a = new Set([1, 2, 3]);
        var b = new Set([4, 3, 2]);
        var intersect = new Set([...a].filter((x) => b.has(x))); // {2, 3}
        
        // 差集
        var a = new Set([1, 2, 3]);
        var b = new Set([4, 3, 2]);
        var difference = new Set([...a].filter((x) => !b.has(x))); // {1}

过滤符合条件的数组项

const fruits = [
  "apple",
  "banana",
  "pear",
  "watermelon",
  "strawberry",
  "arbutus",
];
const hFruits = fruits.filter((fruit) => fruit.startsWith("a"));
console.log("hFruits: ", hFruits);

// hFruits: ["apple", "arbutus"]

检查数组中的某些项目是否匹配条件

const arr1 = [2, 4, 6, 8, 10];
const arr2 = [2, 4, 6, 8, 9];
const isEven = (num) => {
  if (num % 2 === 0) {
    return true;
  }
};

console.log(arr1.every(isEven)); // true
console.log(arr2.every(isEven)); // false

数组的交集

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [4, 5, 6, 7, 8, 9];
const intersection = arr1.filter((num) => arr2.includes(num));
console.log(intersection); // [4, 5]

筛选数组的差异部分

// 法一
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [4, 5, 6, 7, 8, 9];
const difference = arr1.filter((num) => !arr2.includes(num));
const allDifference = [
  ...arr1.filter((num) => !arr2.includes(num)),
  ...arr2.filter((num) => !arr1.includes(num)),
];

console.log(difference); // [1, 2, 3]
console.log(allDifference); // [1, 2, 3, 6, 7, 8, 9]

// 法二
// 比较两个数组,然后返回一个新数组,该数组为两个数组的差异部分,与allDifference同理
function diff(arr1, arr2) {
  var newArr = [];
  arr1 = Array.from(new Set(arr1)); // 去重
  arr2 = Array.from(new Set(arr2)); // 去重
  newArr =arr1.concat(arr2);
  return newArr.filter(x=>!(arr1.includes(x) && arr2.includes(x)))
}

diff([1, 2, 3, 5], [1, 2, 3, 4, 5]); // [4]

对数组中的项目进行排序

const numbers = [52, 9, 23, 16, 20, 99];

// 升序
const asc = [...numbers.sort((a, b) => a - b)];
console.log(asc); // [9, 16, 20, 23, 52, 99]

// 降序
const desc = [...numbers.sort((a, b) => b - a)];
console.log(desc); // [99, 52, 23, 20, 16, 9]

Tips

冒泡排序

  • 实现原理
    • 数组中有 n 个数,比较每相邻两个数,如果前者大于后者,就把两个数交换位置;这样一来,第一轮就可以选出一个最大的数放在最后面;那么经过 n-1(数组的 length - 1) 轮,就完成了所有数的排序。
      sort排序
var arr = [3, 4, 1, 2];
function bubbleSort(arr) {
  var max = arr.length - 1;
  for (var j = 0; j < max; j++) {
    // 声明一个变量,作为标志位
    var done = true;
    for (var i = 0; i < max - j; i++) {
      if (arr[i] > arr[i + 1]) {
        var temp = arr[i];
        arr[i] = arr[i + 1];
        arr[i + 1] = temp;
        done = false;
      }
    }
    if (done) {
      break;
    }
  }
  return arr;
}
bubbleSort(arr);

// 1、外层 for 循环控制循环次数
// 2、内层 for 循环进行两数交换,找每次的最大数,排到最后
// 3、设置一个标志位,减少不必要的循环

数组对象树结构的筛选

function filterTree(nodes, query) {
  // 条件就是节点的title过滤关键字
  let predicate = function (node) {
    if (node.title.includes(query)) {
      return true;
    } else {
      return false;
    }
  };
  // 结束递归的条件
  if (!(nodes && nodes.length)) {
    return [];
  }
  let newChildren = [];
  for (let node of nodes) {
    // 一、带父节点     以下两个条件任何一个成立,当前节点都应该加入到新子节点集中
    //  1. 子孙节点中存在符合条件的,即 subs 数组中有值
    //  2. 自己本身符合条件
    let subs = this.filterTree(node.children, query);
    if (predicate(node)) {
      newChildren.push(node);
    } else if (subs && subs.length) {
      node.children = subs;
      newChildren.push(node);
    }

    // // 二、不带父节点     以下只需要考虑自身的节点满足条件即可,不用带上父节点
    // if (predicate(node)) {
    //   newChildren.push(node);
    //   node.children = this.filterTree(node.children, query);
    // } else {
    //   newChildren.push(...this.filterTree(node.children, query));
    // }
  }
  return newChildren.length ? newChildren : [];
}

  目录