Better

Ethan的博客,欢迎访问交流

JavaScript数组去重

我只想说,我如果不看这篇文章,我是不会知道去重还有这么多种方法的。同时看别人代码优化,很有启发,开拓新思路哇。

方法

双重循环

兼容性好

function unique(array) {
    // res用来存储结果
    var res = [];
    for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {
        for (var j = 0, resLen = res.length; j < resLen; j++ ) {
            if (array[i] === res[j]) {
                break;
            }
        }
        // 如果array[i]是唯一的,那么执行完循环,j等于resLen
        if (j === resLen) {
            res.push(array[i])
        }
    }
    return res;
}

indexOf优化

底层使用===判断是否相等

function unique(array) {
    var res = [];
    for (var i = 0, len = array.length; i < len; i++) {
        var current = array[i];
        if (res.indexOf(current) === -1) {
            res.push(current)
        }
    }
    return res;
}

排序去重

  • var sortedArray = array.concat().sort();先concat的目的是拷贝一份数组。
  • 如果我们对一个已经排好序的数组去重,这种方法效率肯定高于使用 indexOf。
    function unique(array) {
      var res = [];
      var sortedArray = array.concat().sort();
      var seen;
      for (var i = 0, len = sortedArray.length; i < len; i++) {
          // 如果是第一个元素或者相邻的元素不相同
          if (!i || seen !== sortedArray[i]) {
              res.push(sortedArray[i])
          }
          seen = sortedArray[i];
      }
      return res;
    }
    

看看大神怎么优化性能的

这个方法是最想好好理解的,可以说是开拓了一种新思路。参数传递方法的妙用哇。
新需求:字母的大小写视为一致,比如'a'和'A',保留一个就可以了!

// iteratee 英文释义:迭代 重复
function unique(array, isSorted, iteratee) {
    var res = [];
    var seen = [];
    for (var i = 0, len = array.length; i < len; i++) {
        var value = array[i];
        var computed = iteratee ? iteratee(value, i, array) : value;
        if (isSorted) {
            if (!i || seen !== value) {
                res.push(value)
            }
            seen = value;
        }
        else if (iteratee) {
            if (seen.indexOf(computed) === -1) {
                seen.push(computed);
                res.push(value);
            }
        }
        else if (res.indexOf(value) === -1) {
            res.push(value);
        }        
    }
    return res;
}
console.log(unique(array3, false, function(item){
    return typeof item == 'string' ? item.toLowerCase() : item
}));

filter方法

function unique(array) {
    return array.concat().sort().filter(function(item, index, array){
        return !index || item !== array[index - 1]
    })
}

Object 键值对

function unique(array) {
    var obj = {};
    return array.filter(function(item, index, array){
        return obj.hasOwnProperty(item) ? false : (obj[item] = true)
    })
}

上面代码看似没有问题,但是将上和'1'判断为相等的了,因为对象的键值只能是字符串,所以我们可以使用 typeof item + item 拼成字符串作为 key 值来避免这个问题。修改的代码如下:

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

ES6

随着 ES6 的到来,去重的方法又有了进展,比如我们可以使用 Set 和 Map 数据结构,以 Set 为例,ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

// 一
function unique(array) {
   return Array.from(new Set(array));
}
// 二
function unique(array) {
    return [...new Set(array)];
}
// 三
var unique = (a) => [...new Set(a)]
// 四
function unique (arr) {
    const seen = new Map()
    return arr.filter((a) => !seen.has(a) && seen.set(a, 1))
}

大神指引

数组去重



留言