今天分享的是数组对象去重的方式,先看看数组对象的形式:
一、指定条件去重
举个例子:
[
{
"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)