javascript实现数组扁平化的七种方式

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

数组扁平化是面试中的常考点,不仅考验面试者熟练使用各类方法的能力,还考验其灵活编程的能力。下面让我们来看下实现数组扁平化的七种方式。

提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是扁平化?

定义 : 扁平化就是将多维数组变成一维数组,不存在数组的嵌套

二、实现扁平化的方法 封装 flatten

1.最简单的方式( ES6 flat)

Array.prototype.flat是ES6新增的一个数组方法,它的作用就是用来数组扁平化,并且根据传入的参数来决定展开的层级。

参数:
depth(可选) 指定要提取嵌套数组的结构深度,默认值为 1

返回值:
返回一个新数组,包含数组与提取嵌套数组的所有元素的新数组

使用 Infinity,可展开任意深度的嵌套数组
代码如下(示例):

let arr = [1, [2, [3, 4]]];
function flatten_1(arr) {
  return arr.flat(Infinity);
}
console.log(flatten(arr)); //  [1, 2, 3, 4]

直接使用自带的方法可以很快的实现, 但是很显然我们面试的时候如果只会这种方法是不行的。

2.普通递归实现(使用for循环或者forEach都可以)

普通递归的思路很容易理解,就是通过for循环的方式,逐层逐个元素地去展平,如果当前元素是一个数组,那么就对它进行递归处理,再将递归处理的结果拼接到结果数组上。
代码如下(示例):

let arr = [1, [2, [3, 4, 5]]];

function flatten_2(arr) {
    let result = []
    for(let i = 0; i < arr.length; i++) {
        if(Array.isArray(arr[i])) {
            //console.log('数组');
            result = result.concat(flatten(arr[i]));
        }
        else {
            result.push(arr[i])
        }
    }
    return result
}
console.log(flatten_2(arr)); //[1,2,3,4,5]

增加参数控制扁平化深度(相当于手写flat()方法)

// // forEach 遍历数组会自动跳过空元素
const eachFlat = (arr = [],depth = 1)=> {
    const result = [];
    (function flat(arr, depth){
        arr.forEach((item) => {
            // 控制递归深度
            if(Array.isArray(item) && depth > 0) {
                flat(item,depth - 1)
            }
            else {
                // 缓存元素
                result.push(item)
            }
        });
        
    })(arr, depth)
    return result
}
console.log(eachFlat(arr,1)); // [ 1, 2, [ 3, 4, 5 ] ] 
console.log(eachFlat(arr,2)); // [ 1, 2, 3, 4, 5 ]


3、split + toString方法

我们也可以通过 split 和 toString 两个方法,来共同实现数组扁平化。

let arr3 = [1, [2, [3, [4,5]]]];
function flatten_3(arr) {
    return arr.toString().split(',').map(item=>Number(item))
}
console.log(flatten_3(arr3)); // [1,2,3,4,5]

不过需要注意的是,虽然这个方法非常简单,但具有一定的局限性,对于包含引用类型元素的数组来说,在toString过程中会发生类型转换,从而使得转换结果异常,因为对于引用类型转成字符串,会调用引用类型的toString,上面提到不同对象会对它进行改写,例如函数就会得到一个函数体的代码字符串,而不是我们想要的函数引用。

4、扩展运算符实现

扩展运算符是ES6的新特性之一,用它操作数组可以直接展开数组的第一层,利用这个特性,我们可以不使用递归来实现数组的展平,这是因为每一次递归都是对当前层次数组的一次展开,而扩展操作符就是干这工作的。

let arr4 = [1, [2, [3, 4]]];
function flatten_4(arr) {
   while(arr.some(item=> Array.isArray(item))) {
     //console.log(...arr);
     arr = [].concat(...arr)
     //console.log(arr,'arr');
   }
   return arr
}

console.log(flatten_4(arr4));

5、 使用正则替换

看到嵌套的数组,如果在字符串的角度上看就是多了很多[ 和],如果把它们替换就可以实现简单的扁平化

let arr5 = [1, [2, [3, 4]]];
// console.log(JSON.stringify(arr5));
// console.log(JSON.stringify(arr5).replace(/(\[|\])/g, ''));

function flatten5(arr) {
    let str = JSON.stringify(arr).replace(/(\[|\])/g, '')
    str = '['+ str +']'
    //console.log(str,'str'); // '[1,2,3,4]' String
    return JSON.parse(str) // [1,2,3,4]
}
console.log(flatten5(arr5));

6、巧用 reduce方法

reduce是JS数组中非常强大的一个方法,同时也是JS中的一个函数式编程API。

const arr = [1, [2, [3, 4]]];
const flatten = (arr, deep = 1) => {
    if (deep <= 0) return arr;
    return arr.reduce((res, curr) => res.concat(Array.isArray(curr) ? flatten(curr, deep - 1) : curr), [])
}
console.log(arr, 2);
// 输出:[ 1, 2, 3, 4 ]

7、使用 Generator 函数

GeneratorFunction是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行),这里的generator方法的思想也是迭代的(当然前面我迭代的代码,可以把判断是否是array的条件放在if条件当中)。
它不同于普通函数,是可以暂停执行的,所以函数名之前要加星号,以示区别。

let arr7 = [1, [2, [3, 4]]];

function* flatten7(array) {
    for (const item of array) {
        if (Array.isArray(item)) {
           
            yield* flatten7(item);
        } else {
            yield item;
        }
    }
}
const gen = flatten7(arr7)
let res = []
for (let f of gen) {
    res.push(f)
}
console.log(res); [1,2,3,4]
//需要注意的是,调用flatten7(arr7)并不会直接得到结果,需要时用next()或者放在for循环中得到所有结果。

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bin_123ge

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值