文章目录
参考原文:
一、使用堆栈的方式
代码如下(示例):
let arr = [[1,2,3],[3,4,5,5],[6,7,8,9,[11,12,[12,13,[14]]]],10]
function cusFlat(array) {
const stack = [...array] //将原数组先用扩展运算符解构到新的数组中
const res = []
while (stack.length) { //使用while循环,当栈(stack数组)中还有值接着循环
const pop = stack.pop() //每次从栈中吐出一个值,这样数组(栈)的长度就会改变
if (Array.isArray(pop)) { //如果吐出的是数组,则将该数组解构,堆到这个栈的末尾
stack.push(...pop)
}else { //如果吐出的不是数组,则push到一个新的数组中
res.push(pop)
}
}
return res.reverse() //由于push是放到末尾,所以数组顺序需要翻转一下
}
console.log('cusFlat',cusFlat(arr)); //[1,2,3,3,4,5,5,6,7,8,9,11,12,12,13,14,10]
二、使用递归的方式
在使用递归的时候只要记住两点:
1.递归函数第一层或者说最初的目的是要去干什么;
2.递归函数一定要有出口,避免死递归.
代码如下(示例):
function cusFlat(array) {
const res = []
function flatCus(params) {
params.forEach(item => {
if(Array.isArray(item)){
flatCus(item)
}else{
res.push(item)
}
})
}
flatCus(array)
return res
}
console.log('cusFlat',cusFlat(arr)); //[1,2,3,3,4,5,5,6,7,8,9,11,12,12,13,14,10]
三、使用生成器函数generator的方式
代码如下(示例):
function* flatten(array) {
for (const item of array) { //传入的数组是一个可迭代对象,所以可以用for of循环.item为循环的每一项
if (Array.isArray(item)) { //如果item还是为数组,则使用flatten这个生成器函数继续yield出每一项
yield* flatten(item)
}else{ //item为正常值时,yield出来正常的值
yield item
}
}
}
const res = [...flatten(arr)] // 创建出来的flatten()为一个迭代器,迭代器是可以用for of循环的,当然也可以用...扩展元素运算符来循环,然后将迭代器中的每一项扩展到一个新的数组
console.log('flatten',res); //[1,2,3,3,4,5,5,6,7,8,9,11,12,12,13,14,10]
1.生成器函数generator
①generator和普通函数明显的区别就是generator函数带了一个*
②generator一般是和yield关键字配合使用的
③generator最大的特点就是能交出函数的执行权
④generator函数生成的实例是一个迭代器,并通过调用next方法,可以将函数中的yield一步一步执行
⑤generator函数应用的场景较少,一般是封装一个异步函数使用,现基本都被promise代替
function* demoGen(array) {
yield 1
yield 2
yield 3
console.log('yield执行完了')
return 4
}
const iteratorRes = demoGen()
console.log('iteratorRes',iteratorRes); //打印出来的对象是个迭代器
console.log('iteratorRes1',iteratorRes.next()); //iteratorRes1 {value: 1, done: false}
console.log('iteratorRes2',iteratorRes.next()); //iteratorRes2 {value: 2, done: false}
console.log('iteratorRes3',iteratorRes.next()); //iteratorRes3 {value: 3, done: false}
console.log('iteratorRes4',iteratorRes.next()); //yield执行完了 iteratorRes4 {value: 4, done: true}
yield和return关键字差不多,会暂停函数的执行,交给next来控制.yield和next就像收音机上的暂停和播放按钮一样,控制函数的暂停和执行.
value就是yield出来的值,done来告知是否还有yield关键字在函数内部,也可以说是该函数是否执行完毕,如果执行完毕了再去调用.next()方法,则返回{value:undefined,done:true}
用for of循环遍历这个迭代器
for (const iterator of iteratorRes) {
console.log('每一项',iterator);
}
// 每一项 1
// 每一项 2
// 每一项 3
// yield执行完了
四、考虑数组空位
1.将[,1,2,[3,4,[5,6,7,8]]]格式化成[1,2,3,4,5,6,7,8]
代码如下(示例):
// 1.flat()
let arr = [,1,2,[3,,4,[5,,6,7,,8]]]
console.log('arr.flat(Infinity)',arr.flat(Infinity));
// 2.将上述几种方法的else变成else if(item)皆能实现
2.将[,1,2,[3,4,[5,6,7,8]]]格式化成[,1,2,3, ,4,5, ,6,7, ,8]
let arr = [,1,2,[3,,4,[5,,6,7,,8]]]
// 1.使用堆栈
function cusDZFlat(array) {
const stack = [...array]
let res = []
while (stack.length) {
const pop = stack.pop()
if (Array.isArray(pop)) {
stack.push(...pop)
}else if(pop){
res.push(pop)
}else{
res = res.concat([,])
}
}
return res.reverse()
}
console.log('1',cusDZFlat(arr));
// 2.使用递归
function cusDGFlat(array) {
let res = []
function flatCus(params) {
for (let index = 0; index < params.length; index++) {
if(Array.isArray(params[index])){
flatCus(params[index])
}else if(params[index]){
res.push(params[index])
}else{
res = res.concat([,])
}
}
}
flatCus(array)
return res
}
console.log('2',cusDGFlat(arr));
五、使用reduce来实现数组扁平
function cusRedFlat(params) {
const res = params.reduce((acc,cur)=>{
if (Array.isArray(cur)) {
return acc.concat(cusRedFlat(cur))
}else{
return acc.concat(cur)
}
},[])
return res
}
console.log('4',cusRedFlat(arr));
在将数组扁平化的时候需要考虑到的问题:
1.避免不了需要对数组进行循环,考虑到空间复杂度和时间复杂度
2.需要使用哪些方法来对数组进行判断是否是数组