有这样的一组数据:
let list = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
Set 类型是一种叫做 集合 的数据结构,它是 无序的不可以重复的 集合,Set 集合是以 [值,值] 的形式存储元素;
Array.from() 可以将传入的字符串创建为一个数组。
function unique (arr) {
// 利用Set不可重复的特性去重
return Array.from(new Set(arr));
}
console.log(unique(list))
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
注意:不考虑兼容性,这种去重的方法代码最少,但这种方法还无法去掉 重复的 {} 空对象。
新建一个空的结果数组,for 循环原数组,通过 indexOf 判断结果数组 是否存在当前元素,如果有相同的值则跳过,不相同则 push 进数组。
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
let result = [];
for (let i = 0; i < result.length; i++) {
if (result.indexOf(arr[i]) === -1) {
result.push(arr[i])
}
}
return result;
}
console.log(unique(list))
// [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]
注意:这种方法还无法去掉 重复的 {} 和 NaN 对象。
基本思路与 利用 indexOf 去重是一样的,只不过判断结果数组是否存在当前元素方法调整为 includes() 方法。
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
let result = [];
for (let i = 0; i < arr.length; i++) {
if (!result.includes( arr[i])) {
result.push(arr[i])
}
}
return result;
}
console.log(unique(list))
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
注意:这种方法同样无法去掉{} 。
创建空对象存储数组值及其类型,再使用 hasOwnProperty 判断是否存在对象属性。
function unique(arr) {
let obj = {};
return arr.filter((item) => {
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
})
}
console.log(unique(list))
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}]
注意:所有的都去重了 。
使用 filter 遍历数组,使用 indexOf 判断当前元素在数组中的第一个索引是否和当前所引值相同,如果相同则证明之前没有重复的元素,可返回到结果数组中。
indexOf(searchValue, start):
function unique(arr) {
return arr.filter(function(item, index, arr) {
//当前元素,在原始数组中的第一个索引===当前索引值,否则返回当前元素
return arr.indexOf(item, 0) === index;
});
}
console.log(unique(list))
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}]
注意:所有的都去重了 。
利用 sort 函数对数组进行排序后,依次比较前后两个数据是否相等,若相等则将该数据从数组中删除。
function unique(arr) {
// 1.复制数组和数组长度
let arrCopy = [...arr];
// 2.排序
arrCopy.sort((a, b) => {
return a - b;
})
// 3.利用递归比较临近两个值是否相等,若相等则删除;
function loop(index) {
if (index > 0) {
if (arrCopy[index] === arrCopy[index - 1]) {
arrCopy.splice(index, 1)
}
loop(index - 1)
}
}
loop(arr.length - 1);
return arrCopy;
}
console.log(unique(list))
// [1, 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}]
注意:这种方法无法去掉 重复的 {} 对象。
创建一个空 Map 数据结构,遍历需要去重的数组,把数组的每一个元素作为 key 存到 Map 中。由于 Map 中不会出现相同的 key 值,所以最终得到的就是去重后的结果。
function unique(arr) {
// 1.创建一个空的 Map 数据
let map = new Map();
// 2.创建空数组,作为结果数组返回
let resultArr = [];
// 3.利用 map 对象判断数组中是否有相等的值
for (let i = 0; i < arr.length; i++) {
if(map.has(arr[i])){
map.set(arr[i], true);
}else{
map.set(arr[i],false);
resultArr.push(arr[i]);
}
}
return resultArr;
}
console.log(unique(list))
// [1, 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}]
为了更好地理解,在控制台打印了下 map 对象:
注意:这种方法也无法去掉 重复的 {} 对象。
reduce() 方法接收一个函数作为累加器,将数组中不包含的元素添加进来。
function unique(arr) {
return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
console.log(unique(list))
// [1, 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}]
注意:这种方法也无法去掉 重复的 {} 对象。
利用 set 集合不重复的特性,对数组进行去重并使用 […] 语法转化为数组格式,该方法其实就是方法1的简化。
let resultArr = [...new Set(list)];
console.log(resultArr);
// [1, 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}]
注意:这种方法也无法去掉 重复的 {} 对象。
由于以上方法大多无法去掉重复的 {} 对象,这边建议将对象类型的数据单独进行去重,先使用 Object.keys() 方法来获取对象属性的列表,然后再比较比较它们的值。
对象数组结构如下所示:
// 原数据list是这样的 // 去重后list数据是这样的
[{ [{
"tip_id": 1, "tip_id": 1,
"report_category": 0, "report_category": 0,
"remark": "已受理", "remark": "已受理",
}, },
{ {
"tip_id": 2, "tip_id": 2,
"report_category": 12, "report_category": 12,
"remark": "已处罚", "remark": "已处罚",
}, }]
{
"tip_id": 1,
"report_category": 0,
"remark": "已受理"
}]
Map 类型是 键值对 的 有序 列表,而键和值都可以是任意类型。
function unique (arr, uniId) {
const res = new Map();
return arr.filter((item) => !res.has(item[uniId]) && res.set(item[uniId], 1));
}
let resultList = unique(list, "tip_id");
console.log(list);
reduce() 方法对数组中的每个元素按序执行一个提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
第一次执行回调函数时,不存在“上一次的计算结果”。如果需要回调函数从数组索引为 0 的元素开始执行,则需要传递初始值。否则,数组索引为 0 的元素将被用作初始值,迭代器将从第二个元素开始执行(即从索引为 1 而不是 0 的位置开始)。
function unique(arr, uniId) {
let hash = {};
return arr.reduce((accum, item) => {
hash[item[uniId]] ? '' : hash[item[uniId]] = true && accum.push(item)
return accum
}, [])
}
let resultList = unique(list, "tip_id");
console.log(list);
基本思路和 reduce 是一样的,只不过是用 for 循环代替 reduce。
function unique(arr, uniId) {
let obj = {}
let resultArr = []
for(var i = 0; i < arr.length; i++) {
if(!obj[arr[i][uniId]]) {
resultArr.push(arr[i]);
obj[arr[i][uniId]] = true;
}
}
return resultArr;
}
let resultList = unique(list, "tip_id");
console.log(list);
以上就是我总结的 数组去重 和 对象数组去重 的 全部方法,后续如果想到更好的解决方案,也会记录在这里。