JS的数组去重的8种方法

7 篇文章 0 订阅
4 篇文章 0 订阅

题外话:今天周六openDay,日常上班,上午做做题,下午看看TS,安排的满满当当。

前天 Kill Eve Season3 完结。好像大家都比较喜欢最后小变态说的那句:Now we walk, and we never look back...

其实我比较喜欢前面那段,有点小浪漫:When I try and think of my future. I just ...See your face over and over again...

不甜吗!!!!早上广播里《人文通识》讲的是杜月笙,今晚回去复习一下《教父》。

数组去重

数组操作老生常谈,leeCode上一道题目解法无数,有时候写了几十行发现人家只写了几行简直要被自己的蠢死。

来一个数组,能有几种去重方法呢。

var arr = [1, 2, 3, 2, '2', '2', '3', 1];

1.双层循环

此方法虽然老旧,比不上一些新函数操作方便,但是重点是 兼容性好!

function unique(arr){
    var res = [];
    for (var i = 0, len = arr.length; i < len; i++) {
        for (var j = 0, resLen = res.length; j < resLen; j++) {
            if (arr[i] === res[j]) { // 如果res数组中包含arr[i] 跳出res数组的循环 看arr的i+1项
                break;
            }
        }
        if (j === resLen) { // res循环到最后没有arr[i] 就加进去
            res.push(arr[i]);
        }
    }
    return res;
}

2. indexOf()

思路同1,简化了一层循环。

function unique(arr){
    var res = [];
    for (var i = 0, len = arr.length; i < len; i++) {
       var cur = arr[i];
        if(res.indexOf(cur) === -1) { // res中不包含cur
            res.push(cur);
        }
    }
    return res;
}

3.排序后去重

用到 sort(),注意两点:

1. sort() 在原数组上进行排序,不生成副本。

2.调用 sort()方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。

var arr = [1, 11, 3, 35, 4, 13];
arr.sort();  // => [1, 11, 13, 3, 35, 4]
arr.sort((a, b) => a - b); // => [1, 3, 4, 11, 13, 35]
arr.sort((a, b) => b - a); // => [35, 13, 11, 4, 3, 1]
function unique(arr){
    var res = [];
    var sortArr = arr.concat().sort(); // 复制数组且排序
    var cur;
    for(var i = 0, len = sortArr.length; i < len; i++) {
        if (!i || cur !== sortArr[i]) {
            res.push(sortArr[i]);
        }
        cur = sortArr[i];
    }
    return res;
}

4.filter()

ES 5 的 filter() 方法,注意两点:

1. 不操作原数组,返回一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

2. 不会对空数组进行检查。

function unique(arr){
    var res = arr.filter((item, index, arr) => {
        return arr.indexOf(item) === index;
        // indexOf()返回某个指定的字符串值在字符串中首次出现的位置。
    })
    return res;
}

5. reduce()

function unique(arr) {
    return arr.reduce((pre, cur) => pre.includes(cur) ? pre : [...pre, cur], []);
}

6.ES6 数据结构Set

ES6提供了 数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。

function unique(arr) {
    return Array.from(new Set(arr));  // new Set() 出来是个对象
}

function unique(arr) {
    return [...new Set(arr)];
}

7.ES6 数据结构Map

ES6提供了 数据结构Map。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

function unique(arr){
    var res = new Map()
    return arr.filter(item => !res.has(item) && res.set(item, 1));
}

---------------去重结束分割线-----别问第8种-----问就继续看-----------------------

特殊类型比较

以上几种方法对于特殊类型有不同表现,下面来对比一下。

var str1 = '1';
var str2 = new String('1');

str1 == str2; // true
str1 === str2; // false

null == null; // true
null === null; // true

undefined == undefined; // true
undefined === undefined; // true

NaN == NaN; // false
NaN === NaN; // false

/a/ == /a/; // false
/a/ === /a/; // false

{} == {}; // false
{} === {}; // false

对于下列数组,上述7种方法的运行结果是什么捏,列个表看看吧。

var arr = [1, 1, '1', '1', null, null, undefined, undefined, new String('1'), new String('1'), /a/, /a/, NaN, NaN];
方法运行结果说明
1.双层循环[1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN]对象和 NaN 不去重
2.indexOf()[1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN]对象和 NaN 不去重
3.sort()后循环[/a/, /a/, 1, "1", String, String, NaN, NaN, null, undefined]对象和 NaN 不去重
4.filter()[1, "1", null, undefined, String, String, /a/, /a/]对象不去重, NaN 会被忽略掉
5.reduce()[1, "1", null, undefined, String, String, /a/, /a/, NaN]对象不去重
6.Set数据结构[1, "1", null, undefined, String, String, /a/, /a/, NaN]对象不去重
7.Map数据结构[1, "1", null, undefined, String, String, /a/, /a/, NaN]对象不去重
8.Object键值对[1, "1", null, undefined, String, /a/, NaN]欧开

哎呀,居然没有一种方法能完全去重,最后加个终极方法吧。

8.Object 键值对

hasOwnProperty()中区分不了string or number,所以用typeof + JSON.stringify()来表示唯一性。

function unique(arr){
    var obj = {};
    return arr.filter((item, index, arr) => {
        return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true);
    })
}

 

参考原文 https://github.com/mqyqingfeng/Blog/issues/27

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值