Source code
function filterRepeat(sourceData) {
if (!sourceData || Object.prototype.toString.call(sourceData) !== '[object Array]')
throw new Error('参数 sourceData 必须是一个数组');
else if (sourceData.length === 0) return sourceData;
let entriesData = [];
let repeatIndexes = [];
entriesData = generatorEntriesData(sourceData);
repeatIndexes = getRepeatIndexes(entriesData);
console.log('----- 重复项的 index -----');
console.log(repeatIndexes, '\n');
return filter(sourceData, repeatIndexes);
}
function generatorEntriesData(sourceData) {
let sourceCacheData = [];
let dataType = '';
let result = null;
for (let data of sourceData) {
dataType = Object.prototype.toString.call(data);
if (dataType === '[object Array]') {
result = generatorEntriesData(data);
} else if (dataType === '[object Object]') {
result = generatorEntriesData(Object.entries(data));
} else if (dataType === '[object Function]') {
result = data.toLocaleString();
} else {
result = data;
}
sourceCacheData.push(result);
}
return sourceCacheData;
}
function getRepeatIndexes(entries) {
let indexes = new Set();
let indexesLen = 0;
let arrIndexes = [];
let entriesCache = new Set();
let isEquals = true;
for (let i = 0; i < entries.length; i++) {
if (Object.prototype.toString.call(entries[i]) === '[object Array]') {
indexesLen = indexes.size;
for (let index of arrIndexes) {
isEquals = isEqualsFn(entries[index], entries[i]);
if (isEquals) {
indexes.add(i);
break;
} else {
isEquals = true;
}
}
if (indexes.size === indexesLen) {
arrIndexes.push(i);
}
} else if (entriesCache.has(entries[i])) {
indexes.add(i);
} else {
entriesCache.add(entries[i]);
}
}
return indexes;
}
function isEqualsFn(p1, p2) {
const p1Type = Object.prototype.toString.call(p1);
const p2Type = Object.prototype.toString.call(p2);
let isEquals = true;
if (p1Type === p2Type) {
if (p1Type === '[object Array]') {
if (p1.length === p2.length) {
for (let i = 0; i < p1.length; i++) {
isEquals = isEqualsFn(p1[i], p2[i]);
if (!isEquals) break;
}
} else {
isEquals = false;
}
} else if (p1Type === '[object Object]') {
isEquals = isEqualsFn(Object.entries(p1).sort(), Object.entries(p2).sort());
} else if (p1Type === '[object Function]') {
isEquals = p1Type.name === p2Type.name &&
p1Type.toLocaleString().length === p2Type.toLocaleString().length;
} else {
isEquals = p1 === p2;
}
} else {
isEquals = false;
}
return isEquals;
}
function filter(sourceData, repeatIndexes) {
let result = [];
sourceData.forEach((item, index) => {
if (!repeatIndexes.has(index)) result.push(item);
});
return result;
}
let sourceData = [
1,
1,
'2',
'2',
null,
null,
undefined,
undefined,
[1, 2],
[1, 2],
[{ id: 1 }, { id: 2 }],
[{ id: 1 }, { id: 2 }],
{
id: 1,
name: 'Tom'
},
{
id: 1,
sayHello() {}
},
{
id: 1,
sayHello() {}
},
{
id: 1,
sayHello() { return 'Hello'; }
},
{
id: 1,
sayHello() { return 'Hello'; }
},
{
id: 2,
sayHello() { return 'Hello'; }
}
];
console.log('----- 去重之前 -----');
console.log(sourceData, '\n');
const filteredData = filterRepeat(sourceData);
console.log('----- 去重之后 -----');
console.log(filteredData);
Test case
Result