数组去重

一般操作

最简单的方式,优点兼容性好,缺点是需要两次 for 循环,性能较差

function unique(list) {
    var result = [];
    for(var i = 0; i < list.length; i++) {
        var arrayItem = list[i];

        for(var j= 0; j< result.length; j++) {
            var resultItem = result[j];
            
            // 如果在结果数组循环中找到了该元素,则跳出循环,进入下一个源数组元素的判断
            if(resultItem === arrayItem) {
                break;
            }
        }
        
        // 如果把结果数组循环完都没有找到该元素,就将该元素压入结果数组中
        if(j === result.length) {
            result.push(arrayItem);
        }
    }
    return result;
}

var array = ['a', 'b', 'c', '1', 0, 'c', 1, '', 1, 0];
console.log(unique(array));  // ["a", "b", "c", "1", 0, 1, ""]

数组的 indexOf 属性

ES5的规范,兼容是IE8以上版本

function unique(list){
    var result = [];
    for(var i = 0; i< list.length; i++) {
        var item = list[i];
        if(result.indexOf(item) === -1) {
            result.push(item);
        }
    }
    return result;
}

数组的 filter 属性

filter() 方法会创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。filter 的回调有三个参数,其中第三个参数是当前元素属于的数组对象,这样我们可以利用 indexOf 属性。filter 兼容到 IE9

function unique(list) {
    var result = list.filter(function (item, index, array){
        // 获取元素在源数组的位置,只返回那些索引等于当前元素索引的值。
        return array.indexOf(item) === index;
    });
    return result;
}

利用 Object 的 key value

function unique(list) {
    var result = [];
    var hashTable = {};
    for(var i = 0; i< list.length; i++) {
        // 如果键对应的值,为真,意味着对象的键中已经有重复的键了。
        if(!hashTable[list[i]]) {
        // 将元素作为对象的键,默认键对应的值为 true, 
            hashTable[list[i]] = true;
            
            // 如果对象中没有这个键,则将这个元素放入结果数组中去。
            result.push(list[i]);
        }
    }
    return result;
}

这种方案的事件复杂度为 O(n), 但是对象的键,默认是字符串类型,这意味着什么呢,数字 1 和 字符串 '1',在键中是相等的,所以,上面这种方法不适合字符串和数字混合的去重。

所以我们将元素的类型也放入对象的键中

function unique(list) {
    var result = [];
    var hashTable = {};
    for(var i = 0; i< list.length; i++) {
        var current = list[i];
        // 字符串拼接元素的类型和元素
        var key = typeof(current) + current;
        if(!hashTable[key]) {
            hashTable[key] = true;
            result.push(current);
        }
    }
    return result;
}

数组的 sort 方法

sort 方法的优点在于利用了排序,返回后一个和前一个不相等的元素。缺点在于改变了元素的本来的排序位置。

function unique(list) {
    return list.concat.sort().filter(function(item, index, array) {
        // !index 表示第 0 个元素应该被返回。
        return !index || item !== list[index-1]
    })
}

function unique(array) {
    array.sort(); // 排序字符串
    array.sort(function(a, b) {
        return a-b; // 排序数字
    })
    
    for(let i=0; i<array.length; i++) {
        if(array[i] === array[i+1]) {
            array.splice(i, 1);
            i--; // 应该将前一个数删除,而不是删除后一个数。是因为元素被删除之后,后面元素的索引会迁移,所以要 i--;
        }
    }
    return array;
}

ES6 Set

ES6 提供了新的数据结构 Set,它类似于数组,但是成员的值都是唯一的,没有重复的值。向 Set 加入值的时候,不会发生类型转变,所以 5 和 '5' 是两个不同的值。Set内部判断两个值是否相同,用的是类似于 "==="的算法,但是区别是,在set内部认为NaN 等于 NaN ;
Set 可以转换为数组,所以很容易实现去重

function unique(list) {
    return Array.from(new Set(list));
}

ES6 Map

ES6 新增了 Map 数据结果,通过 has 和 set 方法就能很方便的对前面的 object key value 方案进行优化。

function unique(list){
    const map = new Map()
    return list.filter((item) => !map.has(item) && map.set(item, true))
}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 数组去重,一般都是在面试的时候才会碰到,一般是要求手写数组去重方法的代码。如果是被提问到,数组去重的方法有哪些?你...
    程序员BUG阅读 4,097评论 0 3
  • 数组去重 是常见的面试考点,所以我就试着深入学习一下。网上也有很多数组去重的文章,但我自己觉得分析地不够深入,其实...
    前端西瓜哥阅读 3,846评论 0 1
  • JavaScript专题之数组去重 前言 数组去重方法老生常谈,既然是常谈,我也来谈谈。 双层循环 也许我们首先想...
    Vicky丶Amor阅读 1,696评论 0 5
  • 一、去重 我在前端面试过程中遇到去重算法的概率为百分之九十,这里就总结下各种去重算法及其复杂度 1. new Se...
    lemonzoey阅读 5,121评论 0 2
  • 今早有点懵,7点多离开住处,根据LP的指引到达一处类似于魔都的旅游集散中心,准备乘长途车到塞哥维亚,去看著名的罗马...
    崔庆生阅读 2,563评论 0 1