首页 > 其他分享 >【面试题】JS的14种去重方法,看看你知道多少(包含数组对象去重)

【面试题】JS的14种去重方法,看看你知道多少(包含数组对象去重)

时间:2023-10-11 13:05:57浏览次数:36  
标签:面试题 name age arr JS null id string 14


前言

JavaScript数组是一种特殊的对象,用于保存多个值在一个连续的内存空间中,也正是因为如此,我们在数组中存储大量数据,但是巨大的数据量难免会有重复的,但我们并不需要重复的数据,这个时候就需要就数组进行去重,来达到每个数组都是唯一的,这样的数据才是我们想要的。

数组中值类型数据去重

使用sort去重

首先使用sort对数组排序,然后单循环判断

let arr = [1, 1, "2", "2", "string", "string", null, null, undefined, undefined];

arr.sort((a, b) => a - b);
for (let i = 0; i < arr.length; i++) {
//这里一定要多加一个条件,否者undfined就会被完全删除
  if (arr[i] === arr[i + 1] && i + 1 < arr.length) {
    arr.splice(i, 1);
    i--;
  }
}
console.log(arr);//[ null, 1, '2', 'string', undefined ]

使用递归去重

这种方法嘛,就是为了去重才去重的,可以使用,但完全不推荐

let arr = [1, "2", 1, "2", "string", null, "string", null, undefined, undefined];

//其实整体与第一种循环无异,只是利用了递归的特性
arr.sort((a, b) => a - b);
function recursion(index) {
  if (index >= 1) {
  //判断相同都会删除
    if (arr[index] === arr[index - 1]) {
      arr.splice(index, 1);
    }
    //并且走递归
    recursion(index - 1);
  }
}
recursion(arr.length - 1);

console.log(arr);//[ null, 1, '2', 'string', undefined ]

使用filter去重

filter都知道,条件成立就返回,这里主要是搭配了indexOf返回索引值的特性来实现的

let arr = [1, "2", 1, "2", "string", null, "string", null, undefined, undefined];

//整体感觉还挺简单,就是indexOf会返回所符合条件的第一个值索引值,然后就会跳出循环
//所以每个数只能有一次与filter的index相同
arr = arr.filter((item, index) => {
  return arr.indexOf(item) === index;
});
console.log(arr);//[ 1, '2', 'string', null, undefined ]

使用对象属性去重

我们都知道对象的属性有且只能有一个,我们就可以利用这个特性,来对数组中的值去重

let arr = [1, "2", 1, "2", "string", null, "string", null, undefined, undefined];

const obj = {};
const newArr = [];
arr.forEach((item) => {
//对象的值没有赋值之前默认undfined,所以为假,会走进判断
//当再次遇到这个属性的时候已经有值了,并且为真,则会跳过
  if (!obj[item]) {
    obj[item] = true;
    newArr.push(item);
  }
});

console.log(newArr);//[ 1, '2', 'string', null, undefined ]

使用reduce和includes去重

reduce这个方法搭配includes,可以简便快捷的去重(这里reduce方法都会的吧)

let arr = [1, "2", 1, "2", "string", null, "string", null, undefined, undefined];

arr = arr.reduce((prev, cur) => {
//当prev种不存在当前循环遍历的值,就会执行push操作,如果存在,那就存在呗,没事了
  prev.includes(cur) || prev.push(cur);
  return prev;
}, []);

console.log(arr);//[ 1, '2', 'string', null, undefined ]

使用reduce和indexOf去重

这一种跟配合indexOf是类似差不多了,当indexOf找不到就会返回-1

let arr = [1, "2", 1, "2", "string", null, "string", null, undefined, undefined];

arr = arr.reduce((prev, cur) => {
//这里当为真了,就会执行后面的push,上面那种就是当为假了 就会执行后面push
  prev.indexOf(cur) === -1 && prev.push(cur);
  return prev;
}, []);

console.log(arr);//[ 1, '2', 'string', null, undefined ]

双重循环去重

利用两个for循环,进行对比来达到去重的效果

let arr = [1, "2", 1, "2", "string", null, "string", null, undefined, undefined];

for (let i = 0; i < arr.length; i++) {
  for (let j = i + 1; j < arr.length; j++) {
  //利用两层循环,对比是否有相同的值
    if (arr[i] === arr[j]) {
      arr.splice(j, 1);
      //删除值后-1,否者会跳过一个元素
      j--;
    }
  }
}

console.log(arr);//[ 1, '2', 'string', null, undefined ]

使用indexof去重

这个就是利用indexOf的特性去重,当为-1的时候才会新填元素

let arr = [1, "2", 1, "2", "string", null, "string", null, undefined, undefined];

const newArr = [];
for (let i = 0; i < arr.length; i++) {
  if (newArr.indexOf(arr[i]) === -1) {
  //找不到就添加,找到了就证明已经有了,就略过
    newArr.push(arr[i]);
  }
}

console.log(newArr);//[ 1, '2', 'string', null, undefined ]

使用Set去重

Set对象允许你存储任何类型(无论是原始值还是对象引用)的唯一值。

let arr = [1, "2", 1, "2", "string", null, "string", null, undefined, undefined];

//所以就可以利用扩展运算符和new Set 来进行去重
arr = [...new Set(arr)];

console.log(newArr);//[ 1, '2', 'string', null, undefined ]

数组对象去重

在开发中我们很少遇到值类型的数组需要去重,一般情况下都是数组包对象的形式,但是当数组中的对象有重复的时候,该如何去重呢?毕竟作为引用类型的对象,每一个都是唯一的

利用对象的特性对数组对象去重

使用循环,利用对象的特性进行去重

const arr = [
  { id: 1, name: "张三", age: 18 },
  { id: 2, name: "李四", age: 13 },
  { id: 3, name: "张三", age: 15 },
  { id: 2, name: "王五", age: 16 },
  { id: 4, name: "赵六", age: 18 },
];

const obj = {};
const newArr = [];
arr.forEach((item) => {
//循环遍历,判断对象属性是否为真,为假就将数据添加到新数组中
  obj[item.id] ? "" : (obj[item.id] = true && newArr.push(item));
});
console.log(newArr);
//[
//  { id: 1, name: '张三', age: 18 },
//  { id: 2, name: '李四', age: 13 },
//  { id: 3, name: '张三', age: 15 },
//  { id: 4, name: '赵六', age: 18 }
//]

利用findIndex对数组对象去重

数组有个findIndex方法,会循环遍历,return真的时候会返回当前索引,找不到就返回-1

const arr = [
  { id: 1, name: "张三", age: 18 },
  { id: 2, name: "李四", age: 13 },
  { id: 3, name: "张三", age: 15 },
  { id: 2, name: "王五", age: 16 },
  { id: 4, name: "赵六", age: 18 },
];

const newArr = [];
arr.forEach((item) => {
  if (newArr.findIndex((item1) => item1.id === item.id) === -1) {
    newArr.push(item);
  }
});
console.log(newArr);
//[
//  { id: 1, name: '张三', age: 18 },
//  { id: 2, name: '李四', age: 13 },
//  { id: 3, name: '张三', age: 15 },
//  { id: 4, name: '赵六', age: 18 }
//]

使用reduce对数组对象去重

reduce()  方法对数组中的每个元素按序执行一个提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。

const arr = [
  { id: 1, name: "张三", age: 18 },
  { id: 2, name: "李四", age: 13 },
  { id: 3, name: "张三", age: 15 },
  { id: 2, name: "王五", age: 16 },
  { id: 4, name: "赵六", age: 18 },
];

const obj = {};
//跟单遍历循环去重差不多,只是少定义了一个新的数组,主要还是对数组方法的使用
const newArr = arr.reduce((pre, cur) => {
  obj[cur.id] ? "" : (obj[cur.id] = true && pre.push(cur));
  return pre;
}, []);
console.log(newArr);
//[
//  { id: 1, name: '张三', age: 18 },
//  { id: 2, name: '李四', age: 13 },
//  { id: 3, name: '张三', age: 15 },
//  { id: 4, name: '赵六', age: 18 }
//]

双重循环对数组对象去重

双重循环去重和值类型去重类似,相互对比他们的id来达到去重的效果

const arr = [
  { id: 1, name: "张三", age: 18 },
  { id: 2, name: "李四", age: 13 },
  { id: 3, name: "张三", age: 15 },
  { id: 2, name: "王五", age: 16 },
  { id: 4, name: "赵六", age: 18 },
];

for (let i = 0; i < arr.length; i++) {
  for (let j = i + 1; j < arr.length; j++) {
    if (arr[i].id === arr[j].id) {
      arr.splice(j, 1);
      j--;
    }
  }
}
console.log(arr);
//[
//  { id: 1, name: '张三', age: 18 },
//  { id: 2, name: '李四', age: 13 },
//  { id: 3, name: '张三', age: 15 },
//  { id: 4, name: '赵六', age: 18 }
//]

使用递归对数组对象去重

递归去重,跟值类型去重类似,操作方法也是类似的,当然也是不推荐使用的

const arr = [
  { id: 1, name: "张三", age: 18 },
  { id: 2, name: "李四", age: 13 },
  { id: 3, name: "张三", age: 15 },
  { id: 2, name: "王五", age: 16 },
  { id: 4, name: "赵六", age: 18 },
];

const obj = {};
const newArr = [];
function recursion(v) {
  if (v >= 0) {
    if (!obj[arr[v].id]) {
      obj[arr[v].id] = true;
      newArr.push(arr[v]);
    }
    recursion(v - 1);
  }
}
recursion(arr.length - 1);
console.log(newArr);
//[
//  { id: 4, name: '赵六', age: 18 },
//  { id: 2, name: '王五', age: 16 },
//  { id: 3, name: '张三', age: 15 },
//  { id: 1, name: '张三', age: 18 }
//]

结尾

数组去重在生产中是必不可少的操作,当获取到大量数据的时候,必定会有重复的数据,后端处理不好,只能由前端来进行处理,方法虽然比较多,虽然上面说了14种去重方式,但有些方法都差不多,适合自己的最好,只要会一种去重方式,就能解决99%的场景需求。

标签:面试题,name,age,arr,JS,null,id,string,14
From: https://blog.51cto.com/u_14627797/7809116

相关文章

  • 20个提升效率的JS简写技巧,告别屎山!
    JavaScript中有很多简写技巧,可以缩短代码长度、减少冗余,并且提高代码的可读性和可维护性。本文将介绍20个提升效率的JS简写技巧,助你告别屎山,轻松编写优雅的代码!移除数组假值可以使用filter()结合Boolean来简化移除数组假值操作。假值指的是在条件判断中被视为false的值,......
  • 谈谈"求线段交点"的几种算法(js实现,完整版)
    谈谈"求线段交点"的几种算法(js实现,完整版)"求线段交点"是一种非常基础的几何计算,在很多游戏中都会被使用到. 下面我就现学现卖的把最近才学会的一些"求线段交点"的算法说一说,希望对大家有所帮助. 本文讲的内容都很初级,主要是面向和我一样的初学者,所以请各位算法帝......
  • fastjson
    fastjson将java中的类和json相互转化的一个工具.简单使用javabean类转jsonpublicclassFastjsonTest{publicstaticvoidmain(String[]args){Useruser=newUser();Stringjson=JSON.toJSONString(user);System.out.println(json);......
  • JS实现判断点是否在多边形范围内
    JS实现判断点是否在多边形范围内 一、说明在GIS领域,判断点是否在多边形范围内是一个基础方法,这里主要说下实现原理。原理比较简单,就是有一个GIS理论,一个点向一个方向发送射线,射线与多边形各个边相交的交点如果是奇数说明点在多边形范围内。 (图片引用自:https://blog.cs......
  • fiddler 使用自动相应 替换js
    fiddler使用自动相应替换js   ......
  • vite.config.js base 与 vue-router base
    vite.config.jsbase决定了打包后,资源引用的前缀base:'/hlw/'linkref='/hlw/assets'打包后的dist要放到/hlw路径下base的值与process.env.BASE_URL、import.meta.env.BASE_URL一致vuerouter的base决定了,多页面的访问路径当vite.config.js与router中的base......
  • .NET 8 RC 2 发布,将在11月14日发布正式版
    微软2023-10-10发布了.NET8RC2,下一站是.NET8正式发布,就在下个月NetConf2023[1](11月14日)期间正式发布,我们也开始筹备第四届中国.NET开发者峰会了。经过长达一年时间的开发,.NET8规划的所有主要的新功能都已推出,.NET8及其所有组件现在距离正式发布还有一个月的时间,接下......
  • 14.1 Socket 套接字编程入门
    Winsock是Windows操作系统上的套接字API,用于在网络上进行数据通信。套接字通信是一种允许应用程序在计算机网络上进行实时数据交换的技术。通过使用Windows提供的API,应用程序可以创建一个套接字来进行数据通信。这个套接字可以绑定到一个端口,以允许其他应用程序连接它。另外,Winsoc......
  • jquery.form.js与file文件域、document.domain有冲突
    jquery.form.js的ajaxForm、ajaxSubmit方法无法成功执行回调函数:1.用response.getWriter().out()给客户端打印数据与<scripttype="text/javascript">document.domain="XXX.com";</script>使用jquery.form.js的ajaxForm、ajaxSubmit方法,......
  • struts2+hibernate+spring+jquery返回json List列表
    1.引入包:struts2-json-plugin-2.1.8.1.jarjson-lib-2.1.jarcommons-collections-3.2.1.jarcommons-beanutils-1.8.2.jarcommons-lang-2.4.jarezmorph-1.0.6.jar,其他的包略,这几个包是返回json形式的数据必须的2.<packagename="default"extends="js......