经常会遇到一些业务场景会需要我们对一个数组进行去重,基本数据类型的一维数组比较好办,使用reduce
方法扫一遍即可实现去重,但是很多时候是通过后端返回一些数据,如果后端没有进行去重的操作,那么就只能把锅甩到前端了。。。
场景
例如现在从后端接收到了一串数据:
let arr = [
{
a: '1234',
b: '5678'
},
{
a: '1234',
b: '56178'
},
{
a: '1234',
b: '5678'
},
{
a: '1234',
b: '51123678'
},
{
a: '1234',
b: 'abc'
},
{
b: 'abc',
a: '1234'
}
]
里面有一些数据是重合的,因此需要进行去重处理,有些可能会立马想到使用JSON.stringify
方法将两两转换成字符串做全等匹配,但是这样是不靠谱的,因为json对象中key是无序的,只要键值对稍微调换一下位置就会出错。
目前我只想到最笨的方法,就是利用冒泡排序的思想,将数组中所有的数据都进行两两匹配,将两个对象中的键值对依次匹配,如果两个对象中属性值相等的次数等于了对象中的所有属性个数,说明两个对象中的值完全相等。
方法1
let flag = 0;
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
let pre = arr[i];
let next = arr[j];
for (let key in pre) {
// 有一个属性相等,flag+1
if (pre[key] === next[key]) {
flag++;
}
}
// 如果相等的属性个数为一个对象的全部属性个数,说明完全重合
if (flag === Object.keys(pre).length) {
arr.splice(j, 1);
}
// 清除一个之后flag清零重新计数
flag = 0;
}
}
方法2
function isObjEqual(o1, o2) {
let props1 = Object.getOwnPropertyNames(o1);
let props2 = Object.getOwnPropertyNames(o2);
if (props1.length !== props2.length) {
return false;
}
for (let i = 0, max = props1.length; i < max; i++) {
let propName = props1[i];
if (o1[propName] !== o2[propName]) {
return false;
}
}
return true;
}
let newArr = arr.reduce((prev, cur) => {
let flag = false;
for (let i = 0, len = prev.length; i < len; i++) {
if (isObjEqual(prev[i], cur)) {
flag = true;
}
}
if (!flag) {
prev.push(cur);
}
return prev;
}, [])
注意点
以上提到的两种方法仅针对于以上指定场景中的情况,并且对象中的属性个数完全相等,并且数组中每个对象中的值都为基本数据类型。