数组扁平化

文章目录

参考原文:

1.数组concat_面试官连环追问

2.MDN Array.prototype.flat()

一、使用堆栈的方式

代码如下(示例):

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.需要使用哪些方法来对数组进行判断是否是数组

上一篇:背包、队列和栈的实现(基于链表)


下一篇:背包、队列和栈的实现(基于数组)