资讯专栏INFORMATION COLUMN

数组去重

RyanHoo / 2427人阅读

摘要:很容易给出的方案是当给定数组变成时,发现结果依然还是,而实际上我们期待的结果应该是。为了解决这个问题,遍历数组元素,与已保存的元素对比的时候还应该考虑元素的类型,如下这样就得到了我们想要的结果。

很容易给出的方案是:

function arrayUnique(target) {
  var result = [target[0]];
  var temp = {};
  temp[target[0]] = true;
  for (var i = 1, len = target.length; i < len; i++) {
    if(temp[target[i]] === undefined) {
        result.push(target[i]);
        temp[target[i]] = true;
    }
  }
  return result;
}

arrayUnique([1, 2, 3, 4]); // [1, 2, 3, 4]
arrayUnique([1, 2, 3, 4, "1"]); // [1, 2, 3, 4]

当给定数组变成[1, 2, 3, 4, "1"]时,发现结果依然还是 [1, 2, 3, 4],而实际上我们期待的结果应该是[1, 2, 3, 4, "1"]。
原因很简单,Object 会将属性的 key 值都转成 String 类型,比如,

var a = {1: 3, "3": 9}

Object.getOwnPropertyNames(a) // ["1", "3"]

上述例子中,两个 key 值都被转换成了字符串,再看一下下面一个例子:

var a = {
    1: 3,
    "3": 9
}
Object.prototype.toString = function() {
    return 3;
}

console.log(a[{k: 1}]); // 9

当 key 值是一个object 的时候, 会先调用 toString 将该 object 转成 字符串,再查找。
为了解决这个问题,遍历数组元素,与已保存的元素对比的时候还应该考虑元素的类型,如下:

function arrayUnique(target) {
  var result = [target[0]];
  var temp = {};
  temp[target[0]] = {};
  temp[target[0]][(typeof target[0])] = 1;
  for (var i = 1, targetLen = target.length; i < targetLen; i++) {
    console.log(temp[target[i]], typeof target[i], temp[target[i]][typeof target[i]]);
    if(temp[target[i]] && temp[target[i]][typeof target[i]] === 1) {
        continue;
    }

    result.push(target[i]);
  
    if(typeof temp[target[i]] === "undefined") {
        temp[target[i]] = {};
        temp[target[i]][typeof target[i]] = 1;
    } else {
        temp[target[i]][typeof target[i]] = 1;
    }
  }
  return result;
}

arrayUnique([1, "1", 1, 5, "5"); // [1, "1", 5, "5"]

这样就得到了我们想要的结果。有人会考虑temp对象自带了一个__proto__和length属性,可能在比较中会对结果造成影响。但在测试中,这两个属性只能通过点方法获取,比如temp.__proto__, temp.length,而我们实际比较中使用的是方括号,并不能获取到这两个属性。所以貌似不用太担心,但小心为上,还是使用了Object.create(null),使对象尽可能的纯粹。

function arrayUnique(target) {
  var result = [target[0]];
  var temp = Object.create(null);
  temp[target[0]] = Object.create(null);
  temp[target[0]][(typeof target[0])] = 1;
  for (var i = 1, targetLen = target.length; i < targetLen; i++) {
    console.log(temp[target[i]], typeof target[i], temp[target[i]][typeof target[i]]);
    if(temp[target[i]] && temp[target[i]][typeof target[i]] === 1) {
        continue;
    }

    result.push(target[i]);
  
    if(typeof temp[target[i]] === "undefined") {
        temp[target[i]] = Object.create(null);
        temp[target[i]][typeof target[i]] = 1;
    } else {
        temp[target[i]][typeof target[i]] = 1;
    }
  }
  return result;
}

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

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

相关文章

  • JS数组去重总结

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

    whinc 评论0 收藏0
  • 跟underscore一起学数组去重

    摘要:引子数组去重是一个老生常谈的话题,在面试中也经常会被问道。其中如果数组是排序的,去重运算效率更高,因为排序能够将相同的数排列在一起,方便前后比较。当数组有序对于对象的去重,我们知道为,所以使用比较对象在实际场景中没有意义。 引子 数组去重是一个老生常谈的话题,在面试中也经常会被问道。对于去重,有两种主流思想: 先排序,线性遍历后去重,时间复杂度O(n*log2n); 使用哈希,空间换...

    flybywind 评论0 收藏0
  • JavaScript专题之数组去重

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

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

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

    rozbo 评论0 收藏0
  • JavaScript数组方法之数组去重方法

    摘要:工作过程中经常会用到数组去重,用到的时候往往一时想不到好方法,所以这里来总结一下去重方法。和方法分别为添加成员方法和得到键值方法。因此,利用方法也可以实现数组的去重。 工作过程中经常会用到数组去重,用到的时候往往一时想不到好方法,所以这里来总结一下去重方法。使用es6去重代码很简单,而且ES6已经相当普及了。所以先来介绍一下es6中的方法。 1.ES6中Map结构方法 function...

    CarlBenjamin 评论0 收藏0

发表评论

0条评论

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