JS数组去重

593 阅读2分钟

题目:如何实现数组去重?

假设有数组 array = [1,5,2,3,4,2,3,1,3,4]

你要写一个函数 unique,使得

unique(array) 的值为 [1,5,2,3,4]

也就是把重复的值都去掉,只保留不重复的值。

方法1:利用indexOf

function uniqueByIndexOf(array) {
    var tempArray = [];
    for (let i = 0; i < array.length; i++) {
        if (tempArray.indexOf(array[i]) === -1) {
            tempArray.push(array[i]);
        }
    }
    return tempArray;
}

算法分析

indexOf本身是一个单层循环操作,所以uniqueByIndexOf函数的算法实际上是一个双层循环,因此算法的时间复杂度是O(n²),运行速度不快;在空间上,该算法额外引入了数组对象tempArray,开辟了新内存空间。

方法2:利用Set

function uniqueBySet(array) {
    const s = new Set();
    array.forEach(item => s.add(item));
    return Array.from(s);
}

算法分析:

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

由于Set还是基于数组的数据结构,因此uniqueBySet函数的算法和uniqueByIndexOf一样都是双重循环,算法的时间复杂度是O(n²),运行速度不快;在空间上,该算法额外引入了Set对象s,开辟了新内存空间。

方法3:利用Map

function uniqueByMap(array) {
    const m = new Map();
    for (let i = 0; i < array.length; i++) {
        if (!m.has(array[i])) {
            m.set(array[i], 0);
        }
    }
    return [...m.keys()];
}

算法分析:

Map也是ES6提供的新数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

由于Map是基于hash的数据结构,查找(has)和插入(set)操作的时间复杂度都是O(1),所以uniqueByMap算法的时间复杂度是O(n),是本文3个算法中效率最高的算法。

在空间上,该算法额外引入了Map对象m,开辟了新内存空间。Map在程序运行时会比数组和Set占用更多的内存,可以算作是uniqueByMap算法的一个小小的缺点。