indexOf

简单而且可以加中文,但是兼容性不好,indexOF兼容到ie9

 function uniq(arr) {
var temp = [];
for (let i = 0; i < arr.length; i++) {
if (temp.indexOf(arr[i]) == -1) {
temp.push(arr[i])
}
}
return temp;
}
console.log(uniq([1, 2, 3, 2, 34, "a", "b", "a", 2, 5, 2, 62, ]));

【排序后相邻去除法】

简单,去重排序一起做。但必须是纯数组,不能在数字中混入字符串

 function uniq3(array) {
array.sort((a, b) => {
return a - b
});
var temp = [array[0]]; //关键点,先把第一个放进去
for (let i = 1; i < array.length; i++) { //i从1开始
if (array[i] !== temp[temp.length - 1]) {
temp.push(array[i])
}
}
return temp;
}
console.log(uniq3([1, 2, 1, 2, 12, 13, 235, 3])); // 缺点就是不能加入字符串
console.log(uniq3([1, 2, "b", 1, 2, 12, 13, 235, 3, "a"])); // 缺点就是不能加入字符串

【根据上边改成数组中字符串排序去重法】

 function uniq4(array) {
array.sort((a, b) => {
return (a+'').charCodeAt() - (b+'').charCodeAt()
});
var temp = [array[0]]; //关键点,先把第一个放进去
for (let i = 1; i < array.length; i++) { //i从1开始
if (array[i] !== temp[temp.length - 1]) {
temp.push(array[i])
}
}
return temp;
}
console.log(uniq4(['w', 'a', "b", 'w', 'n', 's', 's', 'b', 'e', "a"])); // 缺点就是不能混入别的

【存到对象里一一对比,去重无排序】

思路 - 利用对象的hash键值对方法,快速获取的特点

准备一个对象和一个新数组,

循环原数组时,将数组的值当做对象的键,且对应值为true(/1皆可),

然后每次拿原数组的下一个值都去判断一下对象中是否有这个值,

没有再push到新数组中去,最后返回新数组。

 uniqArr: function (arr) {
var arr = Array.prototype.slice.call(arr),//这里防止伪数组,容错
obj = {},
newArr = [];
obj[arr[0]] = true;//这里没必要
newArr.push(arr[0]);
arr.forEach((el) => {
if (!obj[el]) {//但是这样写,又一个问题,见下边总结
obj[el] = true;//这里写成true,if里少一步隐式转换
newArr.push(el);
}
});
return newArr;
}

总结:

这种写法有一个问题,就是当我们arr中有多个不一样的对象元素(比如[1,{val:212},'a',{c: 1},false,{d:2}]这样时,会发现,只留下了第一个对象{val:212}这样。

控制台效果:

这是因为一个对象值当做obj的键名时会被toString化,得到的是obj['[object Object]'],后边再有对象时在forEach判断里条件不会成立,就不会被push到新数组,因此也就会被过滤掉了。

其原理同这个题:

 var a = {};b = {m: 1};c ={n:2};

 a[b] = 'b';

 a[c] = 'c';

a当中,键名不叫b也不叫c,而是b这个对象被Object.prototype.toString化后的字符串[object Object]。就是同一个原理。

因为我们使用[]来给对象a追加属性,在[]中,是期望是一个字符串类型的值,所以里边的值会被"字符串化",

也就是当我们传的变量是一个{}时,对象会调用自身原型上的Object.prototype.toString进行转化变成字符串[object Object]。

当我们变量是一个数字12,会调用数字的构造类Number原型上重写的toString方法得到一个字符串'12'。

反正都是会转成字符串。即使当变量转为字符串后为特殊值(如NaN)等也不例外:

以上边的缺点引出下边的方法:

【一行代码实现数组去重】

 let newArr = [...new Set([1, 2, 23, 1, "gjf", 1, 6, "gjf","gfj"])]
console.log(newArr)

// 核心

[…new Set([..需要去重的数组..])]

【缺点方法的解决】

上边说道【存到对象里,一一对比进行去重】方法时,有一个缺点是数组内嵌套了对象、数组这些值时,

因为obj[键值]会被字符串化,导致后边出现的多个对象都会被当做重复处理,

所以我们需要在往obj里存值时对这种情况进行一下处理

需要去重的数组:

先看最初的写法:

 function uniq0517(arr){
var obj = {};
var rst = [];
arr.forEach(el => {
if(!obj[el]){
obj[el] = true;
rst.push(el);
}
});
console.log(obj);// 注意下打印的obj
return rst;
}

目标:去掉重复的对象和数组以及其他原始值,但是保留不同的对象和数组.

去重后的结果:

观察发现,除了对象外,都完成了很好的效果。

看打印的obj结果分析问题:

因为数组在obj的中括号[]里进行toString后是字符串'1,23,4'这样,所以可以比较不同。

但是对象不行。对象一律是[object Object]这样,需要对对象进行处理:

我的思路是,如果检测值为对象(就是普通的对象,而不是时间、正则等这种对象,

所以需要toString检测)时,就把这个对象先JSON.stringify化了。再去进行对比。

就像下面这样,JSON.stringify过后的对象绝对可以判断是否全等。

因此数组去重改造过后的代码如下:

 function uniq0517(arr){
var obj = {},
rst = [],
tempEl = '';
arr.forEach(el => {
if(Object.prototype.toString.call(el) === '[object Object]'){
// 证明这个值是一个对象,就事先将对象字符串化。而不是让他调用自己的toString
tempEl = JSON.stringify(el);
}else{
// 其他类型的值时不做改变
tempEl = el;
}
if(!obj[tempEl]){
obj[tempEl] = true;
rst.push(el);
}
});
console.log(obj);
return rst;
}

完美经过检验!

最后拓展,想着把临时obj换成Map数据结构改造一下:

 function uni10519(arr){
// 用Map实现去重 - 但凡引用值都不能去重
let map = new Map(),
rst = [];
arr.forEach(el => {
if(!map.get(el)){// 已有的一个对象再获取,因为地址不同,所以得到false
map.set(el,true);
rst.push(el);
}
});
console.log(map);
return rst;
}
console.log('map试水失败',uni10519(arr20190517));

算了吧。。。引用值地址不同,没法取出来作对比。

同样的,对于这种超级复杂类型的数组,进行去重的话,还得用我最原始的方式进行一一比对。否则set也扑街了:

 function uni10519Set(arr) {
// 用Set实现去重
return [...new Set(arr)];
}
console.log('set试水失败',uni10519Set(arr20190517));// 对象、数组什么的引用值都不能比较相等

JS- 数组去重方法整理的更多相关文章

  1. js数组去重方法整理

    1.思路:定义一个新数组,并存放原数组的第一个元素,然后将原数组的项和新数组的元素一一对比,若不同则存放在新数组中. function unique(arr){ var res = [arr[0]]; ...

  2. JS实现数组去重方法整理

    前言 我们先来看下面的例子,当然来源与网络,地址<删除数组中多个不连续的数组元素的正确姿势> 我们现在将数组中所有的‘ a’ 元素删除: var arr = ['a', 'a', 'b', ...

  3. js 数组去重方法汇总

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  4. 原声js数组去重方法

    数组去重方法 方法一 ---- 利用数组filter + indexOf方法去重 方法二 ---- 利用数组forEach + indexOf方法去重 方法三 ---- 利用数组from方法 + Se ...

  5. js数组去重方法分析与总结

    数组去重经常被人拿来说事,虽然在工作中不常用,但他能够很好的考察js基础知识掌握的深度和广度,下面从js的不同阶段总结一下去重的方法. ES3阶段 该阶段主要通过循环遍历数组从而达到去重的目的 多次循 ...

  6. Js数组去重方法总结

    //方法一 var arr = [1,23,1,1,1,3,23,5,6,7,9,9,8,5]; function removeDuplicatedItem(arr) { for(var i = 0; ...

  7. 三种常用的js数组去重方法

    第一种是比较常规的方法 思路: 1.构建一个新的数组存放结果 2.for循环中每次从原数组中取出一个元素,用这个元素循环与结果数组对比 3.若结果数组中没有该元素,则存到结果数组中 Array.pro ...

  8. js数组去重方法包括Es6(方法有很多,但是需要考虑兼容性和数据类型场景)

    1.Es6提供的方法 <script type="text/javascript"> //ES6里新添加了两个方法,set(set是一种新的数据结构,它可以接收一个数组 ...

  9. js 数组去重方法总结

    var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, ...

  10. js数组去重方法集合

    //第一种方法,新建一个空数组,将原来的数组循环逐个与新数组的成员做比较,如果新数组没有该元素就push进来 var arr = ['a', 1, 1, 1, 2, 4, 4, 'b', 'c', ' ...

随机推荐

  1. Dart面向对象编程(二)

    继承: person.dart: class Person{ String name; int age; String _birthday; bool get isAdult => age &g ...

  2. 【CTS2019】珍珠(生成函数)

    [CTS2019]珍珠(生成函数) 题面 LOJ 洛谷 题解 lun题可海星. 首先一个大暴力\(sb\)的\(dp\)是设\(f[i][S]\)表示当前考虑完了前\(i\)个珍珠,\(S\)集合中这 ...

  3. Java学习:网络编程总结

    Java网络编程总结 一.概述 计算机网络是通过传输介质.通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来,实现资源共享和数据传输的系统.网络编程就就是编写程序使联网的两个(或多个)设备( ...

  4. uni-app如何解决在for循环里调用异步请求获取数据顺序混乱问题?

    总结/朱季谦 先前有一次做uni-app的js接口对接时,遇到过这样的情况,在for循环里,调用一个异步请求时,返回来的值顺序是乱的,因此,在以下的代码里,push到数组里的值,每次的顺序可能都是不一 ...

  5. 学习Linq之前必须要了解的扩展方法

    本文主要以下面几个方面来详细讲解扩展方法:在C#3.0之前没有扩展方法的状态(或者你不会使用不知道扩展方法的时候).扩展方法的语法及怎么使用.怎么正确的使用扩展方法: 一.首先说一下在C#3.0之前没 ...

  6. 微服务架构 ------ 插曲 linux LVM磁盘扩容

    1.LVM的基本概念 物理卷(PV):可以在上面建立卷组的媒介,可以是硬盘分区,也可以是硬盘本身或者回环文件,物理卷包括一个特殊的header,其余部分被切割成一块块物理区域. 卷组(VG):将一组物 ...

  7. Struts2处理(jQuery)Ajax请求

    1. Ajax     Ajax(Asynchronous JavaScript and XML,异步JavaScript和XML)时一种创建交互式网页应用的网页开发技术,它并不是一项新的技术,其产生 ...

  8. SpringApplication到底run了什么(上)

    在上篇文章:SpringBoot源码解析:创建SpringApplication对象实例中,我们详细描述了SpringApplication对象实例的创建过程,本篇文章继续看run方法的执行逻辑吧 p ...

  9. c#打开颜色对话框

    用button时间 调出颜色对话框来: private void btnForeColor_Click(object sender, EventArgs e)        {            ...

  10. HubSpot company数据在UI上的展示和通过API方式进行获取

    在网页查看所有的company: https://app.hubspot.com/contacts/6798828/companies/list/view/all/? 打开第一个名为SAP的compa ...