JS对象数组去重


一、数组去重

有这样的一组数据:

let list = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];

1.使用 new Set()

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", {}, {}]

打印控制台:
在这里插入图片描述

注意:不考虑兼容性,这种去重的方法代码最少,但这种方法还无法去掉 重复的 {} 空对象。

2.使用 indexOf 去重

新建一个空的结果数组,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 对象。

3.使用 includes 去重

基本思路与 利用 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", {…}, {…}]

注意:这种方法同样无法去掉{} 。

4.使用 hasOwnProperty

创建空对象存储数组值及其类型,再使用 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", {…}] 

注意:所有的都去重了 。

5.使用 filter

使用 filter 遍历数组,使用 indexOf 判断当前元素在数组中的第一个索引是否和当前所引值相同,如果相同则证明之前没有重复的元素,可返回到结果数组中。

indexOf(searchValue, start)

  • searchvalue:必填,需检索的字符串值或者数组;
  • start: 可非必填,开始检索的位置,它的合法取值是 0 到 arr.length - 1,如省略该参数,则将从字符串的首字符开始检索。
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", {…}] 

注意:所有的都去重了 。

6.使用递归

利用 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', {…}, {…}]

注意:这种方法无法去掉 重复的 {} 对象。

7.利用 Map 数据结构去重

创建一个空 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 对象:
在这里插入图片描述
注意:这种方法也无法去掉 重复的 {} 对象。

8.使用用 reduce + includes

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', {…}, {…}]

注意:这种方法也无法去掉 重复的 {} 对象。

9.使用 new Set() 的简化

利用 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": "已受理" 
}]

1.使用 new Map() 和 filter

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); 

2.使用reduce

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);

3.使用for循环

基本思路和 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);

总结

以上就是我总结的 数组去重对象数组去重 的 全部方法,后续如果想到更好的解决方案,也会记录在这里。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值