数组的去重和扁平化的方法有很多,但实现相同的功能,某些方法有人实现的就很复杂,下面我们来说几个简单的方法。
function unique(arr){
var res = arr.filter((item,index,array)=>{
return array.indexOf(item) === index
})
return res
}
console.log(unique([1,2,1,3,'1','sf']))//[1, 2, 3, "1", "sf"]
数字1
和字符串1
是不会去重的,这就更加合理,因为字符串和数字本来就不是同一玩意。但有些小伙伴可能会用以下方法实现数组去重:
差评的做法:
function unique(arr){
var obj = {
}
var res = []
for(let i=0;i<arr.length;i++){
if(!obj.hasOwnProperty(arr[i])){
obj[arr[i]] = 1
res.push(arr[i])
}
}
return res
}
console.log(unique([1,2,1,3,'1','sf']))//[1, 2, 3, "sf"]
上面就是通过判断obj对象有没有该key,如果没有,obj就添加该属性且将元素放入数组res中,但这种实现是有bug的,因为obj的key本来就是一个字符串,那么数字1
和字符串1
就被obj认为是相同的key,那么就导致把字符串1去掉了。。。。
var unique = arr => [...new Set(arr)]
console.log(unique([1,2,1,3,'1','sf']))//[1, 2, 3, "1", "sf"]
没错,不用感到意外,就一行代码实现了去重,这得归功于ES6实现的Set
对象,点击这里详细学习Set。
数组扁平化就是将 [5, [10, [15,[20]]]] 这种多层的数组拍平成一层 [5,10,15,20]。使用 Array.prototype.flat 可以直接将多层数组拍平成一层:
[5, [10, [15,[20]]]].flat(Infinity) // [5,10,15,20]
Array.prototype.flat() 用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。
不传参数时,默认“拉平”一层,可以传入一个整数,表示想要“拉平”的层数。传入 <=0 的整数将返回原数组,不“拉平”
Infinity 关键字作为参数时,无论多少层嵌套,都会转为一维数组
function flatten(arr){
var result = []
arr.forEach((item)=>{
if(Object.prototype.toString.call(item)==="[object Array]"){
result.push(...flatten(item))
}else{
result.push(item)
}
})
return result
}
console.log(flatten([1,[2,[3]],55]))
原理:判断数组中的每一个元素,如果元素是数组则递归调用flatten()
,否则就直接追加到result
中。
注意:递归效率非常低。。。
function flatten(arr){
while(arr.some(item=>Array.isArray(item))){
arr = [].concat(...arr)
}
return arr
}
原理:通过循环判断元素中是否还存在数组,存在则通过展开运算符
展开数组,每次扒开一层。