Moriarty02/blog

将一个多维数组拍平为一个一维数组

Opened this issue · 3 comments

简单算法02
描述:将一个多维数组拍平为一个一维数组

input

[1,2,3,[4,5],[6,[7,[8]]]]

output

[1,2,3,4,5,6,7,8]

我的解法:

这个题目是面试比较常考的题目

tips:判断是否为数组,一般提到的有三种方式

  1. Object.prototype.toString.call(arr)==="[object Array]"
  2. arr.constructor===Array
  3. Array.isArray(arr)

这三种我更喜欢用constructor
第一种 C++效率其实是最低的
第三种 兼容不好

目前我想到了三个方法

  1. 比较常见的解法是使用递归去遍历数组,wrap声明一个ret
    这个ret对下面的递归来说是一个可见的,可作为最后的输出
function wrap(){
    var ret=[];
    return function flat(a){
        for(var item of a){
            if(item.constructor===Array){
                ret.concat(flat(item))
            }else{
                ret.push(item)
            }
        }
        return ret
    }
}
  1. 这是比较取巧的方法,利用这是一个比较取巧的方法可以利用Array的toString方法将深度的值遍历出来,但是因为toString方法会把数字转化为字符串所以需要map一下把数字转回来,也是这个原因所以这个方法只适合全是数字的数组,如果类型不统一就不能这么了
function flat2(arr){
    return arr.toString().split(",").map(Number)
}
  1. ES6其实原生就支持了这个方法 Array.prototype.flat
function flat3(arr){
    return arr.flat(true)
}

值得提一下的是
这种原生支持的API因为底层是使用C++实现的,相比较下我自己实现的算法最后还需要一步编译成C++,其实原生的才是最快的

你的第一种方法,闭包使用的不太恰当吧,如果我这样使用你的这个函数是有问题的。

let flatten = wrap();
console.log(flatten([1,2,3,[4,5],[6,[7,[8]]]]))  //[1, 2, 3, 4, 5, 6, 7, 8]
console.log(flatten([1,2,3,[4,5],[6,[7,[8]]]]))  //[1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]

你的第一种方法,闭包使用的不太恰当吧,如果我这样使用你的这个函数是有问题的。

let flatten = wrap();
console.log(flatten([1,2,3,[4,5],[6,[7,[8]]]]))  //[1, 2, 3, 4, 5, 6, 7, 8]
console.log(flatten([1,2,3,[4,5],[6,[7,[8]]]]))  //[1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]

感谢提醒~
您看这个样调用不会有问题啦

console.log(wrap()([1,2,3,[4,5],[6,[7,[8]]]])) ;

不过这样确实是调用起来确实很奇怪,我想了想然后改了下

function wrap(arr){
    var ret=[];
    var flat=function(a){
        for(var item of a){
            if(item.constructor===Array){
                ret.concat(flat(item))
            }else{
                ret.push(item)
            }
        }
    }
    flat(arr);
    return ret
}

再次感谢您的回复

ret.concat(flat(item))并不会改变ret的值,而是返回一个新数组
function flat(arr) { let res = [] function helper(arr) { for (let i = 0; i < arr.length; i++) { if (Array.isArray(arr[i])) { helper(arr[i]) continue } res.push(arr[i]) } } helper(arr) return res }
第一次用找了半天也不知道怎么把代码格式化😳