今天分享的是数组对象去重的方式,先看看数组对象的形式:

一、指定条件去重

举个例子:

[
  {
    "name": "yzq",
    "age": 20,
    "gender": true,
    "height": 10
  },
  {
    "name": "yzq",
    "age": 20,
    "gender": false,
    "height": 20
  },
  {
    "name": "xeon",
    "age": 20,
    "gender": true,
    "height": 30
  },
  {
    "name": "xeon",
    "age": 20,
    "gender": true,
    "height": 180
  },
  {
    "name": "xeon",
    "age": 20,
    "gender": false,
    "height": 180
  },
  {
    "name": "yz1",
    "age": 30,
    "gender": true,
    "height": 180
  }
]

1、双重for循环

    let data = [];
    this.persons.forEach(item => {

      if (data.length == 0) {
        data.push(item);
      } else {

        let isDiff = true;//是否不同
        for (let i = 0; i < data.length; i++) {
          let dataItem = data[i];
          if (dataItem.name == item.name && dataItem.age == item.age) {
            /*集合中已经存在相同数据*/
            isDiff = false;
            break;
          }
        }

        if (isDiff) {
          data.push(item);
        }
      }

    });


    console.log('去重后的数据:', data);


在这里插入图片描述
两两比较,如果后一个对象的id值和前一个对象的id值相等,就把后面的对象删除

let arrObj = [
    { name: "小红", id: 1 },
    { name: "小橙", id: 1 },
    { name: "小黄", id: 4 },
    { name: "小绿", id: 3 },
    { name: "小青", id: 1 },
    { name: "小蓝", id: 4 }
];
function fn1(tempArr) {
    for (let i = 0; i < tempArr.length; i++) {
        for (let j = i + 1; j < tempArr.length; j++) {
            if (tempArr[i].id == tempArr[j].id) {
                tempArr.splice(j, 1);
                j--; // 这个别忘咯
            };
        };
    };
    return tempArr;
};
console.log(fn1(arrObj));

2、通过reduce方法

    let obj = {};
    var reduce = this.persons.reduce((curr, next) => {
      /*判断对象中是否已经有该属性  没有的话 push 到 curr数组*/
      obj[next.age + next.name] ? '' : obj[next.age + next.name] = curr.push(next);
      return curr;
    }, []);

    console.log('reduce', reduce);

在这里插入图片描述

3、使用 Lodash 中的 unionWith

记得要先导包

import * as Lodash from 'lodash';
let data = Lodash.unionWith(this.persons, (item1: Person, item2: Person) => {

  return item1.age == item2.age && item1.name == item2.name;
});
console.log('去重后的数据:', data);

在这里插入图片描述

4、indexOf()

定义一个数组存储id的值,然后逐个比较,把id值重复的对象删除即可

let arrObj = [
    { name: "小红", id: 1 },
    { name: "小橙", id: 1 },
    { name: "小黄", id: 4 },
    { name: "小绿", id: 3 },
    { name: "小青", id: 1 },
    { name: "小蓝", id: 4 }
];
function fn2(tempArr) {
    let newArr = []
    for (let i = 0; i < tempArr.length; i++) {
        if (newArr.indexOf(tempArr[i].id) == -1) {
            newArr.push(tempArr[i].id)
        } else {
            tempArr.splice(i, 1)
            i-- // 这个别忘咯
        }
    }
    return tempArr
}
console.log(fn2(arrObj))

5、对象访问属性的方法

采用对象访问属性的方法,判断属性值是否存在

let arrObj = [
    { name: "小红", id: 1 },
    { name: "小橙", id: 1 },
    { name: "小黄", id: 4 },
    { name: "小绿", id: 3 },
    { name: "小青", id: 1 },
    { name: "小蓝", id: 4 }
];
function fn3(tempArr) {
    let result = [];
    let obj = {};
    for (let i = 0; i < tempArr.length; i++) {
        if (!obj[tempArr[i].id]) {
            result.push(tempArr[i]);
            obj[tempArr[i].id] = true;
        };
    };
    return result;
};
console.log(fn3(arrObj));

6、Map()

has方法可以判断Map对象中是否存在指定元素,有则返回true,否则返回false

set方法可以向Map对象添加新元素 map.set(key, value)

values方法可以返回Map对象值的遍历器对象

let arrObj = [
    { name: "小红", id: 1 },
    { name: "小橙", id: 1 },
    { name: "小黄", id: 4 },
    { name: "小绿", id: 3 },
    { name: "小青", id: 1 },
    { name: "小蓝", id: 4 }
];
// 方法一:
let map = new Map();
for (let item of arrObj) {
    if (!map.has(item.id)) {
        map.set(item.id, item);
    };
};
arr = [...map.values()];
console.log(arr);
 
 
 
// 方法二: (代码较为简洁)
const map = new Map();
const newArr = arrObj.filter(v => !map.has(v.id) && map.set(v.id, 1));
console.log(newArr);

以上6种方式,可以根据自己的喜好选择,如有错误,欢迎指正。

二、只要对象的所有属性值相同,则表示相同对象

看个例子:

const arr = [
  { a:1, b:2 },
  { b:2, a:1 },
  { a:1, b:2, c:{ a:1,b:2 } },
  { b:2, a:1, c:{ b:2,a:1 } }
]
// 期望得到
const arr = [
  { a:1, b:2 },
  { a:1, b:2, c:{ a:1,b:2 } }
]

尝试使用new Set()

const arr = [
  { a:1, b:2 },
  { b:2, a:1 },
  { a:1, b:2, c:{ a:1,b:2 } },
  { b:2, a:1, c:{ b:2,a:1 } }
]
const newArr = [...new Set(arr)]
// 结果
// [
//  { a:1, b:2 },
//   { b:2, a:1 },
//  { a:1, b:2, c:{ a:1,b:2 } },
//  { b:2, a:1, c:{ b:2,a:1 } }
// ]

很显然,使用new Set()不行,为啥呢
先看下new Set()的文档
在这里插入图片描述
在set中 +0与-0是不同的 NaN与NaN是相同的,其它值都是通过===来判断

所以 这里为什么用new Set()
无法去重,是因为他看待重的方式,与我们看待重的方式是不一样的
也就是说,只要你的需求里的相同值的定义和new Set()相同值的定义是一致的时候,就可以使用new Set()去重。

理解去重的本质: 什么是重

所以我们再看下这个


const arr = [1,3,2,1,1,2,3]
for(let i = 0; i < arr.length; i++) {
  // 去掉i+1 开始后续的值
  for(let j = i + 1; j < arr.length; j++) {
    if (arr[i] === arr[j]) {
      // 去掉该值
      arr.splice(j, 1)
      j--
    }
  }
}
console.log(arr) // [1,3,2]

所以我们只要更改去重规则

具体实现代码:

const arr = [
  { a:1, b:2 },
  { b:2, a:1 },
  { a:1, b:2, c:{ a:1,b:2 } },
  { b:2, a:1, c:{ b:2,a:1 } }
]

const isObject = (val):boolean => {
  return typeof val === 'object' && val !== null
}

const equals = (val1:any, val2:any):boolean => {
  if (isObject(val1) && isObject(val2)) {
    const keys1 = Object.keys(val1)
    const keys2 = Object.keys(val2)
    if (keys1.length !== keys2.length) return false
    for(const k of keys1) {
      if (!keys2.includes(k)) return false
      if (!equals(val1[k], val2[k])) return false
    }
    return true
  } else {
    return val1 === val2
  }
}

for(let i = 0; i < arr.length; i++) {
  // 去掉i+1 开始后续的值
  for(let j = i + 1; j < arr.length; j++) {
    if (equals(arr[i], arr[j])) {
      // 去掉该值
      arr.splice(j, 1)
      j--
    }
  }
}
console.log(arr)
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐