js数组去重 —— 复习

今天主要就是了解了一下关于数组去重的方法,下面就说说怎么去重,以及去重的方法。

数组去重,这是一个老梗了…今天我又拿出来说了… 我们在考虑全面一点的情况下,数组去重的实现,比如针对NaN,undefined,{}; 这其中涉及的知识点挺多,不信跟着走一波; 这里不考虑浏览器兼容性这些破问题,因为涉及ES5&6

下面就从四个阶段来说

基础版

测试数组

[1,1,’’,’’,‘e’,‘e’,true,‘true’,true,false,false,‘false’,undefined,‘undefined’,undefined,null,‘null’,null]

  • ES5万能的for方法
		/**
         * 使用ES5的for方法来实现
         * 实现方法:
         *    1、定义一个空的数组,用来保存去重后的数据
         *    2、遍历所有的数据,根据下标,判断新数组内是否有这个值,没有的情况下,就推入该新数组。
         *       indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
         *       注释:indexOf() 方法对大小写敏感!
                 注释:如果要检索的字符串值没有出现,则该方法返回 -1。
         *       1、使用indexOf()方法来做三目运算,并判断,
                    如果新的数组内的值等于-1,就说明新数组中没有这个值,然后就是把这个值添加到新的数组内;
                    如果不等于-1,就证明当前的值,在新数组内存在过,把当前的值等于空,即可(即删除)。
        */
        function uniqueUseFor(arr) {
             var temp = []; //一个临时的数组

            //    遍历当前的数组
             for (var i = 0; i < arr.length; i++) {
                 temp.indexOf(arr[i] == -1) ? temp.push(arr[i]) : ""
             }
             return temp;
         }
         console.log(uniqueUseFor(arr));
       // 结果: [1, 1, "", "", "e", "e", true, "true", true, false, false, "false", undefined, "undefined", undefined, null, "null", null]
  • ES5内置的forEach方法
		/**
         * 使用ES5的forEach的方法
         * 实现方法:
         *    1、定义一个空的数组,用来保存去重后的数据
         *    2、遍历所有的数据,拿到每个值,判断新数组内是否有这个值,没有的情况下,就推入该新数组。
         *       indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
         *       注释:indexOf() 方法对大小写敏感!
                 注释:如果要检索的字符串值没有出现,则该方法返回 -1。
         *       1、使用indexOf()方法来做三目运算,并判断,
                    如果新的数组内的值等于-1,就说明新数组中没有这个值,然后就是把这个值添加到新的数组内;
                    如果不等于-1,就证明当前的值,在新数组内存在过,把当前的值等于空,即可(即删除)。
        */
         function uniqueUseFor(arr) {
             var temp = [];
             arr.forEach(item => {
                 temp.indexOf(item) == -1 ? temp.push(item) : ""
             })
             return temp;
         }
         console.log(uniqueUseFor(arr))
        //结果: [1, "", "e", true, "true", false, "false", undefined, "undefined", null, "null"]
  • [ES6]内置的for-of方法
		/** 
         * 使用ES6的for of方法
         * 实现方法:
         *     1、定义一个空的数组,用来保存去重后的数据
         *     2、遍历所有的数据,拿到每个值,判断新数组内是否有这个值,没有的情况下,就推入该新数组。
         *       indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
         *       注释:indexOf() 方法对大小写敏感!
                 注释:如果要检索的字符串值没有出现,则该方法返回 -1。
         *       1、使用indexOf()方法来做三目运算,并判断,
                    如果新的数组内的值等于-1,就说明新数组中没有这个值,然后就是把这个值添加到新的数组内;
                    如果不等于-1,就证明当前的值,在新数组内存在过,把当前的值等于空,即可(即删除)。
         *      
        */
        function uniqueUseFor(arr) {
            var temp = [];
            for (let x of arr) {
                temp.indexOf(x) == -1 ? temp.push(x) : ""
            }
            return temp;
        }
        console.log(uniqueUseFor(arr));
        //结果: [1, "", "e", true, "true", false, "false", undefined, "undefined", null, "null"]

进阶版

包含NaN,undefined,null

测试数组

[1,1,‘true’,true,true,5,‘F’,false, undefined, null,null,undefined, NaN, 0, 1, ‘a’, ‘a’, NaN,‘NaN’]

function uniqueUseNotAllEqual(array) {
        var tmp = [] //一个临时数组
        mark = true; //标识位

        // 遍历当前数组
        for (var i = 0, j = array.length; i < j; i++) {
            // 标识符的作用就是用来判断是否存在NaN,第一次找不到保留到新数组中
            // 然后标识位置改为false是为了再次找到的时候不推入数组
            if (array[i] !== array[i]) {
                // 这里的不等特性,也可以用isNaN判断[ES6]
                mark && tmp.indexOf(array[i]) === -1 ? tmp.push(array[i]) : "";
                mark = false
            } else {
                tmp.indexOf(array[i]) === -1 ? tmp.push(array[i]) : "";
            }
        }
        console.log(tmp)
        return tmp;
    }
    uniqueUseNotAllEqual(array)
	//结果: result: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]
  • ES6内置Array.prototype.includes()大法
 function uniqueCompareUseIncludes(array) {
        // 传入值必须存在,且长度小于等于1的时候直接返回数组
        if (array && array.length <= 1) {
            return array
        } else {
            let tmp = [];   //一个临时数组
            // 遍历当前数组
            for (let x of array) {
                // includes()方法用来判断当前数组是否有指定包含的值,如果有返回true没有返回false
                tmp.includes(x) ? "" : tmp.push(x)
            }
            console.log(tmp)
            return tmp
        }
    }
    uniqueCompareUseIncludes(array)
    //结果: result: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]
[es6] Array.from或扩展运算符[…]结合set大法
/*
* 知识点
* 1.Set的值具有唯一性,内部会自动===比较,
* 是可迭代对象(iterable),有点特殊的是NaN这货虽然有不全等的特性,
* 在Set里面认为是相同的,所以只能有一个
* 2.Array.from和…可以把类似数组【nodelist or arguments】
* 这类可迭代的对象中转为一个标准的数组
*/
// Array.from+Set的方法
let arr = Array.from(new Set([1, 1, 'true', true, true, 5, 'F', false, undefined, null, null, undefined, NaN, 0, 1, 'a', 'a', NaN, 'NaN']))
console.log(arr)

// ... 扩展运算符 +Set的方法
let arrTow = [...new Set([1,1,'true',true,true,5,'F',false, undefined, null,null,undefined, NaN, 0, 1, 'a', 'a', NaN,'NaN'])]
console.log(arr)

高阶版

包含{},NaN,undefined,null

测试数组

let array = [1, 1, ‘true’, true, true, 5, ‘F’, false, undefined, null, null, undefined, NaN, {}, {}, ‘{}’, 0, 1, ‘a’, ‘a’, NaN]

  • ES5 fro-in + call +for 方案
function uniqueUseForIn(array) {
        var tmp = [];
        var emptyObjectMark = true; //标识位
        var NaNObjectMark = true;   //标识位
        // 判断空对象
        function isEmptyObject(object) {
            if (Object.prototype.toString.call(object) === "[object Object]") {
                for (var i in object) {
                    // 存在属性和方法,则不是空对象
                    return false
                }
                return true;
            } else {
                return false
            }
        }

        // 传入值必须存在,且长度等于小于1的时候返回数组
        if (array && array.length <= 1) {
            return array
        } else {
            // 遍历当前数组
            for (var i = 0, j = array.length; i < j; i++) {
                //标识位的作用就是用来判断是否存在NaN和空对象,第一次找到保留到新数组中
                //然后标识位置改为false是为了再次找到的时候不推入数组
                if (isEmptyObject(array[i])) {
                    emptyObjectMark && tmp.indexOf(array[i]) == -1 ? tmp.push(array[i]) : "";
                    emptyObjectMark = false
                } else if (array[i] !== array[i]) {
                    NaNObjectMark && tmp.indexOf(array[i])  == -1 ? tmp.push(array[i]) : "";
                    NaNObjectMark = false
                } else {
                    tmp.indexOf(array[i]) == -1 ? tmp.push(array[i]) : "";
                }
            }
            console.log(tmp)
            return tmp;
        }
    }
    uniqueUseForIn(array)
    //结果: result:[1, "true", true, 5, "F", false, undefined, null, NaN, Object, "{}", 0, "a"] 

拓展版

多维数组扁平化再去重;

测试数组

let array = [1, 1, [[‘true’, true, true, [5, ‘F’], false], undefined], null, null, [undefined, NaN, {}], {}, ‘{}’, 0, 1, ‘a’, ‘a’, NaN]

/*
*   知识点
*       数组扁平化用了递归实现
*       代码也考虑了默认参数,防止不传递参数的时候报错
*       ES5for-in + call + for +递归扁平化方案
*/
function uniqueArrayWithFlattern(array) {
        var _array = array || []
        function isEmptyObject(object) {
            if (Object.prototype.toString.call(object) === "[object Object]") {
                for (var i in object) {
                    return false
                }
                return true
            } else {
                return false
            }
        }

        // 遍历查询判断,扁平化数组 
        function forArrayFlattern(arr) {
            // console.log("fenqian",arr)
            for (var m = 0, n = arr.length; m < n; m++) {

                if (Array.isArray(arr[m])) {
                    // console.log("分割2",_array.splice(m,1))
                    // console.log("分割1",_array)
                    var _tmpSpliceArr = _array.splice(m, 1)[0];
                    // console.log("分割完",_tmpSpliceArr)
                    _array = _array.concat(_tmpSpliceArr)
                    // console.log("==========================",_array)

                    return forArrayFlattern(_array)
                }
            }
            return uniqueArr(_array)
        }

        // 传入值必须存在,且长度小于等于1的时候直接返回数组
        if (_array && _array.length <= 1) {
            return _array
        } else {
            if (Array.isArray(_array)) {
                return forArrayFlattern(_array)
            } else {
                return _array
            }
        }

        // 数组去重
        function uniqueArr(_array) {
            var tmp = [];
            var emptyObjectMark = true;
            var NaNObjectMark = true;

            // 遍历当前数组
            for (var a = 0, b = _array.length; a < b; a++) {
                if (isEmptyObject(array[a])) {
                    emptyObjectMark && tmp.indexOf(_array[a]) == -1 ? tmp.push(_array[a]) : ""
                    emptyObjectMark = false
                } else if (_array[a] !== _array[a]) {
                    NamedNodeMap && tmp.indexOf(_array[a]) == -1 ? tmp.push(_array[a]) : ""
                    NamedNodeMap = false
                } else {
                    tmp.indexOf(_array[a]) == -1 ? tmp.push(_array[a]) : ""
                }
            }
            console.log(tmp)
            return tmp
        }
    }
    uniqueArrayWithFlattern(array)
    // result:[1, null, Object, "{}", 0, "a", NaN, undefined, "true", true, false, 5, "F"]

详细了解移步JS数组去重!!!一篇不怎么靠谱的"深度"水文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值