JavaScript中的数组拍平是什么意思,如何进行数组拍平处理
Admin 2022-06-20 群英技术资讯 1007 次浏览
今天这篇给大家分享的知识是“JavaScript中的数组拍平是什么意思,如何进行数组拍平处理”,小编觉得挺不错的,对大家学习或是工作可能会有所帮助,对此分享发大家做个参考,希望这篇“JavaScript中的数组拍平是什么意思,如何进行数组拍平处理”文章能帮助大家解决问题。概念很简单,意思是将一个“多维”数组降维,比如:
// 原数组是一个“三维”数组 const array = [1, 2, [3, 4, [5, 6], 7], 8, 9] // 可以降成二维 newArray1 = [1, 2, 3, 4, [5, 6], 7, 8, 9] // 也可以降成一维 newArray2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
数组拍平也称数组扁平化、数组降维。
JavaScript标准库中已经实现了数组拍平方法Array.prototype.flat()
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
语法:var newArray = arr.flat([depth])
参数:depth为可选值,表示要遍历多维数组的深度,默认值为1。可以理解为想要展开(或者说降维)的层数。
返回值:遍历到的元素和子数组的元素组合成的新数组
举例:
const array = [1, 2, [3, 4, [5, 6], 7], 8, 9] const newArray1 = array.flat() // 等价于array.flat(1);降1维 // newArray1: [1, 2, 3, 4, [ 5, 6 ], 7, 8, 9] const newArray2 = array.flat(2) // 降2维 // newArray2:[1, 2, 3, 4, 5, 6, 7, 8, 9]
特殊:
depth<=0时,返回的数组和原数组维数一样(注意只是维数一样,空位情况见第3点)
const array = [1, 2, [3, 4, [5, 6], 7], 8, 9] array.flat(-1) // [1, 2, [3, 4, [5, 6], 7], 8, 9]
depth=Infinity,返回的数组变成一维
array.flat(Infinity) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
原数组有空位,flat方法会消除空位,即使是flat(0)也会消除空位,所以第1点说的是“只是维数一样”。并且flat方法展开到哪一层,空位就会消除到哪一层,再深层的空位不会消除
const array1 = [1, , 2, [3, ,4, [5, 6], 7], 8, 9] // 注意这个数组有两个空位 array.flat(0) // [ 1, 2, [ 3, ,4, [ 5, 6 ], 7 ], 8, 9 ] // 第一个空位没了,第二个空位还在
flat方法展开一层(降1维)的步骤:遍历数组,判断当前元素是否为数组,如果不是数组,直接保存;如果是数组,将其展开后保存
flat方法展开多层(降多维)无非就是在展开一层的基础上,使用递归将数组子元素进行同样的操作。
可以将这个方法拆分成三步:
1、如何遍历数组
2、如何判断元素是否为数组
3、递归
实现上述三步,将他们组合起来就可以得到不同的flat实现
方法特别多,这里介绍3类:
1、for相关
for...in是为遍历对象属性而构建的,不建议与数组一起使用
const array = [1, 2, [3, 4, [5, 6], 7], 8, 9]
// for循环
for (let i = 0; i < array.length; i++) {
const element = array[i];
}
// for...of
for (const element of array) {
}
2、数组方法:能直接取到数组元素的方法
// forEach()
array.forEach(element => {
});
// reduce()
array.reduce((pre, cur) => {
const element = cur
}, [])
// map()
array.map(element => {
})
3、数组方法:返回遍历器(Iterator)对象的方法
// 这三种方式仅仅是获得遍历器对象,还需搭配for...of来进行遍历
// keys()
for (let i of array.keys()) {
const element = array[i]
}
// values()
for (let element of array.values() ) {
}
// entries()
for (let [i, element] of array.entries()) {
console.log(array[i])
console.log(element)
}
设有一变量a,判断其是否为数组。这里提供4种方法:
// 方法1 Array.isArray(a) // 方法2 a instanceof Array // 方法3 a.constructor === Array // 方法4 // 使用call来调用Object.prototype上的toString方法 Object.prototype.toString.call(a) === '[object Array]' // 不能这么判断,因为这个toString已经覆盖了Object.prototype.toString // 只有Object.prototype.toString能正确判断类型 a.toString()
递归:对子元素进行同样的操作
function flat() {
let res = []
遍历数组 {
if (当前元素是数组) {
flat(当前元素)得到一维数组
将一维数组拼接到res中
} else {
res.push(当前元素)
}
}
return res
}
挑选遍历方式和判断数组的方式,搭配递归就可以初步实现flat方法,如:
function myFlat(arr) {
let res = [];
for (const item of arr) {
if (Array.isArray(item)) {
res = res.concat(myFlat(item));
// 注意concat方法返回一个新数组,不会改变原数组
} else {
res.push(item);
}
}
return res;
}
myFlat方法可以实现将"多维"数组拉平成一维数组,但是不能指定展开深度depth,并且也无法处理数组空位
处理展开深度其实很简单,我们可以增设一个递归终止条件,即depth<=0,代码如下:
function myFlat(arr, depth = 1) {
// 若depth<=0,则直接返回
if (depth <= 0) {
return arr
}
let res = [];
for (const item of arr) {
if (Array.isArray(item)) {
// 每次递归调用,将depth-1
res = res.concat(myFlat(item, depth - 1));
} else {
res.push(item);
}
}
return res;
}
事实上我们应该尽量避免出现数组空位的情况
前面我们提到了遍历数组的不同方法,它们对于数组空位的处理不尽相同
其中forEach、reduce、map遍历时遇到空位会直接忽略;而for...of则不会忽略,它遇到空位会将其当作undefined处理
因此我们需要改进for...of遍历数组的myFlat方法:
function myFlat(arr, depth = 1) {
if (depth <= 0) {
return arr;
}
let res = [];
for (const item of arr) {
if (Array.isArray(item)) {
res = res.concat(myFlat(item, depth - 1));
} else {
// 判断数组空位
item !== undefined && res.push(item);
}
}
return res;
}
当然也可以使用forEach、map方法来遍历数组,这样就不用手动判断了
但是这里有一个特殊情况需要考虑,就是当depth <= 0时,我们用filter方法来消除数组空位
// forEach
function myFlat(arr, depth = 1) {
if (depth <= 0) {
return arr.filter(item => item !== undefined);
}
let res = [];
arr.forEach((item) => {
if (Array.isArray(item)) {
res = res.concat(myFlat(item, depth - 1));
} else {
res.push(item);
}
});
return res;
}
// map
function myFlat(arr, depth = 1) {
if (depth <= 0) {
return arr.filter(item => item !== undefined);
}
let res = [];
arr.map((item) => {
if (Array.isArray(item)) {
res = res.concat(myFlat(item, depth - 1));
} else {
res.push(item);
}
});
return res;
}
其中,使用reduce方法实现的最为简洁,也是面试中常考的方法之一
function myFlat(arr, depth = 1) {
return depth > 0
? arr.reduce(
(pre, cur) =>
pre.concat(Array.isArray(cur) ? myFlat(cur, depth - 1) : cur),
[]
)
: arr.filter((item) => item !== undefined);
}
理论上,递归方法通常可以转换成非递归方法,即使用栈
function myFlat(arr) {
let res = [];
const stack = [].concat(arr);
while (stack.length > 0) {
const item = stack.pop();
if (Array.isArray(item)) {
// 用扩展运算符展开一层
stack.push(...item);
} else {
item !== undefined && res.unshift(item);
}
}
return res;
}
但是此方法不能指定展开深度,只能彻底展开成一维数组
针对栈不能指定展开深度的缺点进行改进,代码如下:
function myFlat(arr, depth = 1) {
if (depth <= 0) {
return arr.filter((item) => item !== undefined);
}
let res;
let queue = [].concat(arr);
while (depth > 0) {
res = [];
queue.forEach((item) => {
if (Array.isArray(item)) {
// 注意用扩展运算符将数组展开前先用filter方法去掉空位
res.push(...item.filter((e) => e !== undefined));
} else {
res.push(item);
}
});
depth--;
queue = res;
}
return res;
}
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要给大家介绍JS中的Proxy对象,一些朋友可能对Proxy对象的用途以及用法不是很了解,对此下文有详细的介绍,有需要的朋友可以参考下面的代码,接下来我们一起来学习Proxy对象吧。
在jquery中,可以利用“$("元素:not(:last-child)")”语句选择除了最后一列的其它元素;“:last-child”选择器可以选取最后一列元素,“:not()”选择器用于选取除指定元素以外的其它元素。
今天给大家分享的是怎样用JavaScript做年月日三级联动的效果,这一三级联动效果还是比较实用的,实现效果及代码如下,感兴趣的朋友可以参考,接下来跟随小编一起看看吧。
Vue众所周知是一个轻量级的框架,源码仅仅为72.9KB,但是也有它自己的缺点,就是首屏加载会比较慢,这篇文章主要给大家介绍了关于Vue项目首屏性能优化组件的相关资料,需要的朋友可以参考下
这篇文章主要介绍了Node.js的概念和基本原理,对Node.js感兴趣的同学,一定要看一下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008