本文深入解析 JavaScript 数组的高级操作技巧,重点涵盖如何高效找出重复或非重复元素,以及多种数组扁平化(降维)的实现方案。内容从双重循环、Map 统计到 reduce 递归、展开运算符及内置 flat 方法,全面对比二维与多维数组的处理逻辑,帮助开发者掌握不同场景下的最优解。
前言:
数组是 JavaScript 中常见数据类型之一,关于它的一些操作方法,我在这里做一下简单记录和总结。
今天主要介绍:
- 如何找出数组中的重复/非重复元素
- 数组扁平化方法
一、找出数组中的重复元素或非重复元素
双重循环结合 slice 方法可用于找出重复元素。虽然目标仅是识别重复项,但需注意在检查过程中同步进行去重处理,否则外循环仍会对已处理的重复元素进行冗余校验;通过 flag 变量记录重复次数,仅当元素首次被判定为重复时,才将其推入结果数组。
function search(arr){
let res = []
let flag = 0
for(let i = 0;i < arr.length;i++){
for(let j = i+1;j<arr.length;j++){
if(arr[i] === arr[j]){
flag++
if(flag == 1) res.push(arr[i])
arr.splice(j,1)
}
}
flag = 0
}
return res
}利用 map + filter 可以统计每个元素出现的频次。基于这些频次数据,便能灵活筛选出重复元素、出现次数最多的元素,或者完全非重复的元素:
function search(arr){
const map = new Map()
for(item of arr){
if(!map.has(item)){
map.set(item,1)
} else {
map.set(item,map.get(item)+1)
}
}
// 找出重复元素,即出现次数大于1
return [...map.entries()].filter(item => item[1] > 1).map(item => item[0])
// 找出非重复元素,即出现次数等于1
return [...map.entries()].filter(item => item[1] == 1).map(item => item[0])
// 找出重复次数最多的元素
return [...map.entries()]
.filter(item => item[1] == Math.max(...map.values()))
.map(item => item[0])
}二、数组扁平化 / 数组降维
以二维数组 [[],[{a:1}],[],[3,4],5] 为例,经过降维处理后得到结果 [{a:1},3,4,5]。
二维数组:双重循环
该方法需要遍历并检查每个元素是否仍为数组类型。
function flatten(arr){
const res = []
for(let i = 0;i < arr.length; i++){
if(Array.isArray(arr[i])){
for(let j = 0;j < arr[i].length;j++){
res.push(arr[i][j])
}
} else {
res.push(arr[i])
}
}
return res
}二维数组:循环结合 concat
concat 方法本身即可实现数组的一次性降维操作。
function reduceDiemension(arr){
const res = []
for(let i = 0;i < arr.length;i++){
res = res.concat(arr[i])
}
return res
}二维数组:reduce 结合 concat
上述过程本质上属于归并操作,因此可以考虑使用 reduce 来实现。
function flatten(arr){
return arr.reduce((acc,cur) => acc.concat(cur),[])
}二维数组:展开运算符 / apply 结合 concat
通过将原数组展开,或将其作为 apply 的第二个参数,可以将数组转换为独立的参数列表。
function flatten(arr){
// return [].concat([],arr)
return [].concat(...arr)
}对于多维数组,以下面的数组为例:
const arr = [ 1, [ 2,[3], [4,5,6], [7,8,9], 10,11 ], 12, 13, [15,16,17] ]
降维后得到 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17]。
多维数组:toString 结合 split
数组降维可视为移除所有嵌套括号的过程,而数组的 toString 方法恰好能执行此操作,随后调用字符串的 split 方法将字符串重新转换回数组即可。但此方法局限性较大,要求数组内所有元素的数据类型必须一致。
function flattern_numberArray(arr){
return arr.toString().split(",").map(x => Number)
}多维数组:forEach 结合递归
function flatten(arr){
const res = []
arr.forEach(item => {
if(Array.isArray(item)){
flatten(item)
} else {
res.push(item)
}
})
return res
}多维数组:reduce 结合递归
同理,上述过程属于归并操作,可以使用 reduce 来完成。需要注意的是,reduce 的回调函数必须返回一个数组,因此不应再使用 push。
function flatten(arr){
return arr.reduce((acc,cur) => {
if(Array.isArray(cur)){
return [...acc , ...flatten(cur)]
} else {
return [...acc,cur]
}
},[])
}多维数组:while 结合 some
只要数组中仍存在子数组,就使用 concat 对该子数组进行降维。此方法的优势在于无需使用递归。
function flatten(arr){
while(arr.some(item => Array.isArray(item))){
arr = [].concat(...arr)
}
return arr
}不确定维数的数组:flat
对于数组降维,直接使用此前介绍的 flat 是最简便的方式。默认参数为 1,表示仅降维一次;若传入 Infinity 作为参数,则可实现完全降维,最终获得一个一维数组。
到此这篇关于JavaScript 数组常见操作技巧 (二)的文章就介绍到这了,更多相关JavaScript 数组操作技巧内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!