资讯专栏INFORMATION COLUMN

数组去重的方法

sevi_stuo / 944人阅读

摘要:因为使用多带带的接口存取数据所以不用担心与内置属性重名修改上面的方法后得到除了以外还有这种数据类型这是一个集合它不允许重复元素出现。

NaN

NaN属于number,也是一种基本数据类型,只要有一边是 NaN,那么结果就是false

原始值和包装对象

包装对象即基本数据类型经过包装之后得到的对象,作为基本类型值的字符串拥有trim等方法,及length属性,正是由于JS代码会对原始值做一次包装,然后变为了字符串对象,再执行相关的操作。

    // "a".trim();
    
    //该过程在JS解析过程中真实存在
    var tmp = new String("a");
    tmp.trim();

原始值和包装对象的区别在于类型不同。这是最根本的区别,而且虽然是包装"对象",但也会有对象的少部分特性,比如:

    var A = new String("a");
    var B = new String("a");
    var C = "a";
    A == B //false
    A == C //true 
对象和对象

对象可以分为三种:纯对象(plain object)、实例对象、其他类型的对象。

 纯对象指由字面量生成,成员中不含函数和日期、正则表达式等类型的对象。             
纯对象

一元操作符会对对象隐式转换,对象会先调用valueOf方法,然后是toString方法,直到能转换为基本数据类型为止。

而判断两个对象是不是相等时,因为对象保存在堆内存,只有两个对象引用同一个地址,才会相等:

    {} == {}//false
    var a = new Object();
    var b = a;
    console.log(a == b)

如果需要比较两个对象的键名键值对是否相等,可以采取JSON.stringify的方法转换后再比较。

实例对象

通过构造函数生成的对象,这样的对象和纯对象一样无法直接进行外部比较是否相等,可以使用构造函数(类)提供静态方法或实例方法来判断是否相等。

其他对象

指的数组、日期、正则表达式等Object衍生出来的对象,一般需要根据使用场景来构造判断方法,决定两个对象是否相等。

例如日期对象要通过Data.prototype.getTime()方法来获取时间戳判断是否表示同一个时刻,正则需要toString获取原始字面量来判断是否是相同的正则表达式。

== 和 ===

如果判断元素是否相等的方法中,采用的是==比较运算,两边的数据会发生隐式类型转换,这就造成了影响判断结果的因素。

在判断Boolea、Number、String三种类型进行不同类型的 == 比较时,规则是将其转化为数字之后再比较是否相等。

    console.log( "ac" == true )//false
    console.log(123 == "123");//true

而undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。它会被转换成数字,而转换结果为NaN,NaN不等于任何值,所以undefined != false;对于null来说,null表示"没有对象",即该处不应该有值。首先调用Object.valueOf方法返回基本类型值之后在比较,所以null != false
最后一点是undefined == null,这是ECMA-262标准 11.9.3 节的规定。

去重的方法 Array.prototype.indexOf()
    let arr = [12,12,9,2,0,9,8];
    /*
        例如:12第一次出现在0,之后再出现时index为1,
        说明第二个是重复值,所以只返回第一个12,
        但是对于NaN而言indexOf只会为-1,所以不管有几个NaN都会直接跳过
    */
    function unique(arr){
        return arr.filter(function(value,index){
            return arr.indexOf(value) === index;
        })
    }
    
    //indexOf(NaN)则一直为-1,数组中会出现一个或多个NaN(如果存在)
    function unique(arr){
        let ret = [];
        arr.forEach(function(value){
            if(ret.indexOf(value) === -1){
                ret.push(value);
            }
        })
        return ret;
    }
    console.log(unique(arr));

在规范中,indexOf()使用的是全等比较,只要有NaN都是无法判断位置直接跳过的。

    全等比较不能处理NaN的相等性判断,NaN不等于任何值,包括本身。
Array.prototype.includes()

Array.prototype.includes()是ES6中新增的方法,判断数组中是否包含某个元素,上一中indexOf方法可以修改为:

    function unique(arr){
        let ret = [];
        arr.forEach(function(value){
            if(!ret.includes(value)){
                ret.push(value);
            }
        })
        return ret;
    }

includes()方法内部的比较方法是:"SameValueZero",详细规则:

    1. If Type(x) is different from Type(y), return false.

    2. If Type(x) is Number,then
    
        a. If x is NaN and y is NaN, return true.
        
        b. If x is +0 and y is -0, return true.
        
        c. If x is -0 and y is +0, return true.
        
        d. If x is the same Number value as y, return true.
        
        e. Return false.
    
    3. Return SameValueNonNumber(x, y).

注意:如果x、y都是NaN,则返回true,所以includes方法可以判断是否包含了NaN

    var arr = [12,1,"d3",NaN];
    console.log(arr.includes(NaN));//true

由此可见indexOf和includes方法对NaN待的行为不一样。

其他的方法
遍历

遍历是最基本也是最容易想到的方案:

    function unique(arr){
        let isRepeate;
        let ret = [];
        for(var i = 0;len = arr.length,i

去重的部分也是全等操作符实现的,所以对于数组中的NaN而言也会都push进入ret之后返回。

Map Key

Map是一种新的数据类型,就是key的类型没有限制的对象,它的存取使用多带带的get、set接口。因为使用多带带的接口存取数据,所以不用担心key与内置属性重名,修改上面的方法后得到:

    function unique(arr){
        let ret = [];
        let len = arr.length;
        let tmp = new Map();
        for(let i = 0;i
set

除了Map以外,还有Set这种数据类型,这是一个集合,它不允许重复元素出现。
如果重复添加相同的元素,只会储存其中的一个,包括NaN在内。如果将这种特性与数组交换,那么数组就可以直接去重了。

    function unique(arr){
        let ret = new Set(arr);
        return Array.from(set);
    }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82754.html

相关文章

  • JavaScript专题之数组去重

    摘要:专题系列第三篇,讲解各种数组去重方法,并且跟着写一个前言数组去重方法老生常谈,既然是常谈,我也来谈谈。它类似于数组,但是成员的值都是唯一的,没有重复的值。 JavaScript 专题系列第三篇,讲解各种数组去重方法,并且跟着 underscore 写一个 unique API 前言 数组去重方法老生常谈,既然是常谈,我也来谈谈。 双层循环 也许我们首先想到的是使用 indexOf 来循...

    fsmStudy 评论0 收藏0
  • JS数组去重总结

    摘要:数组去重,一般会在面试的时候才会碰到,要求手写数组去重方法的代码。在实际项目中碰到的数组去重,一般都是后台去处理,很少让前端处理数组去重。数组去重的方法一利用去重中最常用如果不考虑兼容性,这种去重的方法代码最少。 数组去重,一般会在面试的时候才会碰到,要求手写数组去重方法的代码。如果是被提问到,数组去重的方法有哪些?你能答出其中的10种,面试官很有可能对你刮目相看。 在实际项目中碰到的...

    whinc 评论0 收藏0
  • <javaScript> 数组重的方法总结(2017年)

    摘要:现在要求去重下面这个数组测试重复重复方法一测试重复重复去重后测试重复是新加的集合集合中的值不会重复。欢迎大家一起讨论提出新的去重方法。有任何错误请在评论指出。 现在要求去重下面这个数组 [1, 2, 3, 3, 3, 0, 1, 2, 测试, 重复, 重复, NaN, NaN, false, false]; 方法一:ES6 Set() let arr = [1, 2, 3, 3, 3,...

    hightopo 评论0 收藏0
  • <javaScript> 数组重的方法总结(2017年)

    摘要:现在要求去重下面这个数组测试重复重复方法一测试重复重复去重后测试重复是新加的集合集合中的值不会重复。欢迎大家一起讨论提出新的去重方法。有任何错误请在评论指出。 现在要求去重下面这个数组 [1, 2, 3, 3, 3, 0, 1, 2, 测试, 重复, 重复, NaN, NaN, false, false]; 方法一:ES6 Set() let arr = [1, 2, 3, 3, 3,...

    YanceyOfficial 评论0 收藏0
  • JavaScript数组去重(12种方法,史上最全)

    摘要:数组去重,一般都是在面试的时候才会碰到,一般是要求手写数组去重方法的代码。如果是被提问到,数组去重的方法有哪些你能答出其中的种,面试官很有可能对你刮目相看。数组去重的方法一利用去重中最常用不考虑兼容性,这种去重的方法代码最少。 数组去重,一般都是在面试的时候才会碰到,一般是要求手写数组去重方法的代码。如果是被提问到,数组去重的方法有哪些?你能答出其中的10种,面试官很有可能对你刮目相看...

    rozbo 评论0 收藏0

发表评论

0条评论

sevi_stuo

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<