关于javascript:深度剖析JavaScript数组去重8种方法

31次阅读

共计 2682 个字符,预计需要花费 7 分钟才能阅读完成。

前言

在工作时,解决后端传来的一棵树,偶尔发现最初生成的数组存在反复的值。这种时候,当然是要和后端进行交换的。尽管在前端也能够解决,然而如果这棵树也被应用到其余中央,那就须要屡次解决,显然前端对数组进行去重是不合理的。但去重的办法也须要把握,于是有了这篇文章。

数组去重的 8 种办法

先来个数组,把所有类型都蕴含进来:

const arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}]

一、利用 new Set():

这种办法是 ES6 种最罕用的数组去重办法。

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

console.log(deduplication(arr))

二、利用开展运算符“…”:

这种办法不言而喻,就是简化了 new Set()。其实应该和 new Set() 算作同一种办法。

console.log([...new Set(arr)])

三、利用 for 循环 +splice() 去重:

太根底了,但根底的货色最重要。关键在于 j = i + 1,这一步操作将内外层循环紧密联系起来,就是说如果外层的 i 为 0,则内层的 j 为从 1 开始遍历,也就是说,每次循环都会比拟 i = 0 和 j = 从 1 开始的每一个元素,判断这两个元素是否全等,如果全等则将索引为 j 的元素从数组移出,也就是说!!!如果第一趟的数组 length 为 12,则第二趟它的 length 为 12 或更小。

function deduplication(arr) {for (let i = 0; i < arr.length; i++) {for (let j = i + 1; j < arr.length; j++) {if (arr[i] === arr[j]) {arr.splice(j, 1)
            }
        }
    }
    return arr
}

四、利用 indexOf():

也很根底,也很重要,重点在于对空数组应用 indexOf 办法。咱们都晓得如果 indexOf 的元素如果在数组中不存在,则会返回 -1,于是利用这个反思路,如果是 - 1 就将这个值推到一个新的数组中。

function deduplication(arr) {if (!Array.isArray(arr)) {throw Error("TypeError: 参数必须为数组类型")
    }
    let newArr = []
    for (let i = 0; i < arr.length; i++) {if (newArr.indexOf(arr[i]) === -1) {newArr.push(arr[i])
        }
    }
    return newArr
}

五、利用 sort():

先对数组进行排序,而后把排序后的第一个元素放到新数组中,这么做是为了避免 i – 1 < 0,而后 for 循环时 i 的初始值就是 1。而后后一个和前一个比拟,如果不全等则推到新数组中。

function deduplication(arr) {if (!Array.isArray(arr)) {throw Error("TypeError: 参数必须为数组类型")
    }
    arr.sort()
    let newArr = [arr[0]]
    for (let i = 1; i < arr.length; i++) {if (arr[i] !== arr[i - 1]) {newArr.push(arr[i])
        }
    }
    return newArr
}

六、利用 includes():

原理很简略,但须要充沛了解 includes 这个办法。它返回的是一个 boolean 类型值,就是说如果这个数组蕴含这个值则为 true,否则为 false。依照这个逻辑,如果一个新数组中蕴含了这个值则不会往这个数组里 push 这个元素。反过来说,如果这个值不在新数组中,那么就把这个值 push 到这个新数组。

function deduplication(arr) {if (!Array.isArray(arr)) {throw Error("TypeError: 参数必须为数组类型")
    }
    let newArr = []
    for (let i = 0; i < arr.length; i++) {if (!newArr.includes(arr[i])) {newArr.push(arr[i])
        }
    }
    return newArr
}

七、利用 filter():

对数组进行过滤,return 前面的内容是过滤的条件,会返回一个新的数组。这里的条件利用了 indexOf(item, 0),这个用法很少用到但并不难理解,item 不必多说示意的是要查找的元素,而 0 则示意 start,也就是起始地位,从索引为 0 开始查找。那么进行过滤的条件就示意,如果这个元素在原数组中首次呈现的地位等于以后项的索引则 push 到新数组中。

function deduplication(arr) {return arr.filter((item, index, arr) => {//console.log(item, index, arr) // 以后项、以后项索引、数组自身
        //console.log(arr.indexOf(item, 0)) // 以后项在原数组首次呈现的地位
        return arr.indexOf(item, 0) === index
    })
}

八、利用 reduce():

首先须要对 reduce 进行一个深刻理解。图中写错了,不是和,是计算结果。例如 return prev + next 则返回的是和,同样 return prev * next 则返回的是乘积。

还是举个例子吧:

而后开始利用 reduce 进行去重,了解了 reduce 的用法之后就简略很多了。这段代码的关键在于传入初始值“[]”,就是说首先须要让 prev 变成一个数组,而后在遍历时判断这个数组中是否蕴含了以后值,如果曾经蕴含则 prev 不变,如果没有则将以后值拼接到 prev 中。

function deduplication(arr) {return arr.reduce((prev, next) => {// console.log(prev, next) //prev 初始为 []
        // console.log(Array.isArray(prev)) //true
        return prev.includes(next) ? prev : prev.concat(next)
    }, []) //“[]”为传递给函数的初始值}

tips:数组的 concat 能够拼接任意对象

总结

数组去重这种操作在前端简直不会用到,除非某些特地状况下。但钻研这些办法可能让咱们对其用法以及原理有更加粗浅的把握和了解。


Keep foolish, keep hungry.

正文完
 0