美文网首页程序员让前端飞
实现一个数组(包含对象等类型元素)去重函数

实现一个数组(包含对象等类型元素)去重函数

作者: alanwhy | 来源:发表于2021-01-14 09:24 被阅读0次

我们之前看过了 手写数组去重、扁平化函数 ,以及 不产生新数组,删除数组里的重复元素 ,这里再次加深一下,如果是数组元素包含对象等类型,又该如何去重喃?

示例如下:

  1. 如传入的数组元素为 [123, "meili", "123", "mogu", 123] ,则输出: [123, "meili", "123", "mogu"]
  2. 如传入的数组元素为 [123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"] ,则输出: [123, [1, 2, 3], [1, "2", 3], "meili"]
  3. 如传入的数组元素为 [123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"] ,则输出: [123, {a: 1}, {a: {b: 1}}, {a: "1"}, "meili"]

基础:JSON.stringify 去重

const removeDuplicates = (arr) => {
  let map = new Map();
  arr.forEach((item) => {
    map.set(JSON.stringify(item), item);
  });
  return [...map.values()];
};

// 测试
removeDuplicates([123, "meili", "123", "mogu", 123]);
// [123, "meili", "123", "mogu"]
removeDuplicates([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]);
// [123, [1, 2, 3], [1, "2", 3], "meili"]
removeDuplicates([
  123,
  { a: 1 },
  { a: { b: 1 } },
  { a: "1" },
  { a: { b: 1 } },
  "meili",
]);
// [123, {a: 1}, a: {b: 1}, {a: "1"}, "meili"]

深入一下

使用 JSON.stringify ,如果数组元素是 object 类型且里面键的顺序不同则会认为是两个不同放入数组元素

let o1 = { a: 1, b: 2 };
let o2 = { b: 2, a: 1 };
JSON.stringify(o1);
// "{"a":1,"b":2}"
JSON.stringify(o2);
// "{"b":2,"a":1}"
JSON.stringify(o1) === JSON.stringify(o2);
// false

解决思路:

一个数组(包含对象等类型元素)去重函数,需要在基础类型判断相等条件下满足以下条件:

  • 如果元素是数组类型,则需要数组中的每一项相等
  • 如果元素是对象类型,则需要对象中的每个键值对相等

去重本身就是遍历数组,然后比较数组中的每一项是否相等而已,所以关键步骤有两步:比较去重

比较:

  • 首先判断类型是否一致,类型不一致则返回认为两个数组元素是不同的,否则继续
  • 如果是数组类型,则递归比较数组中的每个元素是否相等
  • 如果是对象类型,则递归比较对象中的每个键值对是否相等
  • 否则,直接 === 比较

去重:

  • 采用 reduce 去重,初始 accumulator[]
  • 采用 findIndex 找到 accumulator 是否包含相同元素,如果不包含则加入,否则不加入
  • 返回最终的 accumulator ,则为去重后的数组

代码实现:

// 获取类型
const getType = (function () {
  const class2type = {
    "[object Boolean]": "boolean",
    "[object Number]": "number",
    "[object String]": "string",
    "[object Function]": "function",
    "[object Array]": "array",
    "[object Date]": "date",
    "[object RegExp]": "regexp",
    "[object Object]": "object",
    "[object Error]": "error",
    "[object Symbol]": "symbol",
  };

  return function getType(obj) {
    if (obj == null) {
      return obj + "";
    }
    // javascript高级程序设计中提供了一种方法,可以通用的来判断原始数据类型和引用数据类型
    const str = Object.prototype.toString.call(obj);
    return typeof obj === "object" || typeof obj === "function"
      ? class2type[str] || "object"
      : typeof obj;
  };
})();

/**
 * 判断两个元素是否相等
 * @param {any} o1 比较元素
 * @param {any} o2 其他元素
 * @returns {Boolean} 是否相等
 */
const isEqual = (o1, o2) => {
  const t1 = getType(o1);
  const t2 = getType(o2);

  // 比较类型是否一致
  if (t1 !== t2) return false;

  // 类型一致
  if (t1 === "array") {
    // 首先判断数组包含元素个数是否相等
    if (o1.length !== o2.length) return false;
    // 比较两个数组中的每个元素
    return o1.every((item, i) => {
      // return item === target
      return isEqual(item, o2[i]);
    });
  }

  if (t2 === "object") {
    // object类型比较类似数组
    const keysArr = Object.keys(o1);
    if (keysArr.length !== Object.keys(o2).length) return false;
    // 比较每一个元素
    return keysArr.every((k) => {
      return isEqual(o1[k], o2[k]);
    });
  }

  return o1 === o2;
};

// 数组去重
const removeDuplicates = (arr) => {
  return arr.reduce((accumulator, current) => {
    const hasIndex = accumulator.findIndex((item) => isEqual(current, item));
    if (hasIndex === -1) {
      accumulator.push(current);
    }
    return accumulator;
  }, []);
};

// 测试
removeDuplicates([
  123,
  { a: 1 },
  { a: { b: 1 } },
  { a: "1" },
  { a: { b: 1 } },
  "meili",
  { a: 1, b: 2 },
  { b: 2, a: 1 },
]);
// [123, {a: 1}, a: {b: 1}, {a: "1"}, "meili", {a: 1, b: 2}]

原文链接:实现一个数组(包含对象等类型元素)去重函数

相关文章

  • 实现一个数组(包含对象等类型元素)去重函数

    我们之前看过了 手写数组去重、扁平化函数 ,以及 不产生新数组,删除数组里的重复元素 ,这里再次加深一下,如果是数...

  • 工具方法

    对象数组如何去重: reduce 实现对象数组去重复: 实现一个函数判断数据类型: 查找字符串中出现最多的字符和个...

  • js常用方法

    类型判断 数组 对象 去重方法(一) 数组 对象 去重方法(二) 数组(字符串)一个元素出现的次数 删除数组中一个...

  • 前端开发工程师必备系列-3分钟让你搞清楚,对象元素的数组去重实现

    3分钟让你搞清楚,对象元素的数组去重实现方法 今天我们来讲讲,对象元素的数组去重实现,普通简单的数组我们就不讲的,...

  • 对象的浅拷贝和深拷贝

    我们先定义一个对象,包含数字、数组、对象、函数、undefined等类型 浅拷贝就只是复制对象的引用(堆和栈的关系...

  • 数组去重的几种方式

    上篇我们写到了数组中包含多条对象的去重方式数组中包含多条对象的去重方式,今天我们就写一下普通数组去重吧. 数组去重...

  • js实现通用深度克隆

    我们知道对于原始类型以及对象类型中的函数是可以直接通过“=”复制来实现克隆,而对于对象和数组,则需要遍历每一个元素...

  • Array集结号

    实现数组去重的几种方法 数组去重一 数组去重二 利用数组indexof+push实现数组去重 数组去重三 利用对象...

  • 学习TypeScript 对象

    对象是包含一组键值对的实例。 值可以是标量、函数、数组、对象等: TypeScript 类型模板 sites.sa...

  • javascript学习笔记--数组

    数组也是一个对象,用来存储一些值(元素)。数组中的元素可以是任何数据类型 1.创建一个数组对象://构造函数方法,...

网友评论

    本文标题:实现一个数组(包含对象等类型元素)去重函数

    本文链接:https://www.haomeiwen.com/subject/qzbmaktx.html