javascript之数组去重

204 阅读2分钟

1、indexOf

function uniqueIndexOf(arr){
    var result = [];
    for (let i = 0, len = arr.length; i < len; i++) {
        
        if (result.indexOf(arr[i]) === -1) {
            result.push(arr[i]);
        }
    }
    return result;
}

2、fiter+indexOf

function uniqueFilterIndexOf(arr) {
    return arr.filter(function(item, index, array){
        return array.indexOf(item) === index;
    });
}

3、includes

function uniqueIncludes(arr) {
    var result = [];
    for (let i = 0, len = arr.length; i < len; i++) {

        if (!result.includes(arr[i])) {
            result.push(arr[i]);
        }
    }
    return result;
}

4、sort

function uniqueSort(arr) {
    var result = [];
    var prevItem = arr[0];

    var newArr = arr.concat().sort();

    for (let i = 0, len = newArr.length; i < len; i++) {

        if (!i || prevItem !== newArr[i]) {
            result.push(newArr[i]);
        }
        prevItem = newArr[i];
    }
    return result;
}

5、filter+sort

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

6、object键值

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

对象类型obj[1]与obj['1']是一致的,因为对象的键值只能是字符串, 还有如下结果

JSON.stringify(NaN);   // 'null'
JSON.stringify(null);  // 'null'

JSON.stringify(NaN) === JSON.stringify(null) // true

所以使用typeof item + JSON.stringify(item) 作为唯一key

7、set

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

8、set + from

function uniqueSetFrom(arr) {
    return Array.from(new Set(arr));
}

9、改进

如果数组中要求不区分大小写,如

var arr = [1, 'a', 'A', 2];

function uniqueIncludesIteratee(arr, iteratee) {
    var result = [];
    var seen = [];

    for (let i = 0, len = arr.length; i < len; i++) {

        let item = arr[i];
        let computed = iteratee ? iteratee(item, i, arr) : item;

        if (seen.indexOf(computed) === -1) {
            seen.push(computed);
            result.push(item);//注意此句是item,而不是computed
        }
    }
    return result;
}

uniqueIncludesIteratee(arr, function(item, index, array){
    return typeof item == 'string' ? item.toLowerCase() : item;
});
//[1, 'a', 2]

结论

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

1 == 1   //true
1 === 1  //true
'1' == '1'  //true
'1' === '1'  //true
null == null   //true
null === null //true
undefined == undefined //true
undefined === undefined //true
str1 == str2 //true
str1 === str2 //false
/a/ ==  /a/ //false
/a/ ===  /a/ //false
NaN == NaN //false
NaN === NaN //false

var arr = [
    1, 1, 
    '1', '1', 
    null, null, 
    undefined, undefined, 
    new String('1'), new String('1'),
     /a/, /a/, 
     NaN, NaN
];

uniqueIndexOf(arr);
方法名称 结果 说明
indexOf [1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN] NaN和对象都不去重
filter + indexOf [1, "1", null, undefined, String, String, /a/, /a/] NaN被忽略,对象不去重
includes [1, "1", null, undefined, String, String, /a/, /a/, NaN] NaN去重,对象不去重
sort [/a/, /a/, 1, "1", String, String, NaN, NaN, null, undefined] NaN和对象都不去重
filter + sort [/a/, /a/, 1, "1", String, String, NaN, NaN, null, undefined] NaN和对象都不去重
object [1, "1", null, undefined, String, /a/, NaN] 都去重(对于顺序不同的对象数据还是有问题)
set [1, "1", null, undefined, String, String, /a/, /a/, NaN] NaN去重,对象不去重
set + from [1, "1", null, undefined, String, String, /a/, /a/, NaN] NaN去重,对象不去重
[NaN].indexOf(NaN) //-1
[NaN].includes(NaN) //true

主要对于NaN和对象类型数据的判断,存在不同

参考:github.com/mqyqingfeng…