面试官:数组扁平化的方法你知道多少?

前言

当一个数组多维时,怎么将其变成一维,从而实现数组扁平化呢?实现数组扁平化的方法有多种,接下来通过一些代码实例来介绍五种方法。拿下面试官!

正文

递归

概念:在一个函数中直接或间接地调用自身的方式

实现阶乘

阶乘n!=n*(n-1)*(n-2)...1,即n!=n(n-1)!,所有可以通过递归的方式来实现。

代码实现:

scss 复制代码
function mul(n) {
    if (n === 1) {
        return 1;
    } 
    return n * mul(n - 1);
}

实现斐波拉契数列

斐波拉契数列:1 1 2 3 5 8 13 21 34...

观察上面的数列可以发现它们之间的关系为fb(n - 1) + fb(n - 2)=fb(n),所以可以通过递归的方式来实现。

代码实现:

scss 复制代码
function fb(n) {
if (n === 1 || n === 2) {
    return 1;
}
return fb(n - 1) + fb(n - 2);
}

给出数组arr = [1, 2, [3, 4, [5]]],实现将数组扁平化,以下为实现的五种方法:

数组自带的flat()方法

ini 复制代码
const arr = [1, 2, [3, 4, [5]]];
const newArr = arr.flat(Infinity);
console.log(newArr);

递归的方法

插播!先介绍一下关于concat()的方法和解构的概念

concat():

用于将一个或多个数组连接返回形成的一个新数组,原数组不会发生改变。

两个数组的连接:

ini 复制代码
let arr = [1, 2]
let arr2 = [3, 4]
let allArr = arr.concat(arr2);

console.log(allArr, arr);

三个数组的连接:

ini 复制代码
let arr = [1, 2]
let arr2 = [3, 4]
let arr3 = [1, 2, 3, 4, 5, 6, 7, 8, 9]

let allArr = arr.concat(arr2, arr3);

console.log(allArr, arr);

上面的allArr = arr.concat(arr2, arr3);还可以写成 allArr = arr.concat(arr2).concat(arr3);

解构

通过解构将数组的元素直接分配给变量,...x将剩下所有的值分给该变量,如果有多个,则以数组的形式赋值给该变量,解构只能一层一层解。

ini 复制代码
let arr3 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let [a, b, ...c] = arr3;

console.log(a, b, c);

所以连接两个数组也可以通过解构和数组的方式来实现,对两个数组进行解构,然后放在一个数组中

ini 复制代码
let arr = [1, 2]
let arr2 = [3, 4]
let allArr = [...arr, ...arr2];

console.log(allArr, arr);

通过for循环遍历数组,如果遍历到非数组则将其push到新建的·数组res中,反之,则采用递归的方式再次遍历该数组,并将再次遍历到的结果与第一次遍历的res数组连接起来,因为遍历三次得到的res分别为[1,2]、[3,4]、[5],所以每次递归再次调用该函数时都要将res与下一次的结果连接起来,才能得到[1,2,3,4,5],下面使用两种方法来实现连接

使用concat方法

ini 复制代码
const arr = [1, 2, [3, 4, [5]]];

function flatten(arr) {
let res = [];
for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
        res = res.concat( flatten(arr[i]));
    }
    else{
        res.push(arr[i]);
    }
}
return res;
}

const newArr = flatten(arr);

console.log(newArr);

使用解构方法

ini 复制代码
const arr = [1, 2, [3, 4, [5]]];

function flatten(arr) {
let res = [];
for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
    res = [...res, ...flatten(arr[i])];
    }
    else{
        res.push(arr[i]);
    }
}
return res;
}

const newArr = flatten(arr);

console.log(newArr);

toString() + split()的方法

  • 先将数组通过toString()方法转换为字符串'1','2'',3','4','5'
  • 通过split方法以逗号为分隔符将上面的字符串变为数组['1','2'',3','4','5']
  • 通过map遍历该数组,并将数组内的元素转为number类型,结果为[1,2,3,4,5]
ini 复制代码
const arr = [1, 2, 3, [4, [5]] ];
let str = arr.toString();

const newArr = str.split(',').map((item) => {
    return  Number(item);
});

console.log(newArr);

但是! toString方法有缺陷,只能处理数组中只有数字类型的情况

reduce()+concat的方法 -- 递归

javascript 复制代码
array.reduce(callbackFn(pre, item, index, arr){}, initialValue])
  • callbackFn:回调函数,包含四个参数:
  • pre:累计器累存回调的返回值;它是上一次调用回调时返回的累积值,或者是初始值(initialValue)。
  • item:数组中当前被处理的元素。
  • index(可选):当前元素在数组中的索引。默认值:从0开始。
  • arr(可选):调用了reduce()方法的数组本身。
  • initialValue(可选):作为第一次调用 callbackFn 函数时 pre 的值。如果省略,则 pre 的初始值为数组的第一个元素,item 从第二个元素开始。 通过reduce遍历该数组,pre为上一次reduce的结果,所以pre+item可以实现将所有的数组中的值相加起来,initialValue为0,即pre初始为0,pre+item-->0+1 1+2 3+3 6+4 10+5 15+6 21+7,所以结果为28
ini 复制代码
const arr = [1, 2, 3, 4, 5, 6, 7];
let sum = arr.reduce(function(pre, item, index, arr) { // 上一次reduce的执行结果
  return pre + item;
}, 0)

console.log(sum);

通过reduce遍历该数组,将initialValue初始值为一个空数组,所以pre初始值为[],先判断遍历到的item是否为数组,如果为数组就进行递归,不是则为原来的item,然后将pre和递归返回的结果或者item通过concat连接起来,再将其返回。

javascript 复制代码
const arr = [1, 2, [3, 4, [5]] ];

function flatten(arr) {
    return arr.reduce((pre, item) => {
       return pre.concat(Array.isArray(item) ? flatten(item) : item); // [1, 2] [3, 4] [5]
    }, [])
}

console.log(flatten(arr));

some+解构+concat的方法

some():用于检测数组中的元素是否符合条件,数组中的至少有一个元素符合条件,符合返回true,否则,则返回false

c 复制代码
array.some(callbackFn(element, index, array){}, thisArg)
  • callbackFn:测试数组中每个元素的函数。该函数接收三个参数:
  • element:当前遍历的元素。
  • index(可选):当前元素的索引。
  • array(可选):调用 some() 的数组本身。
  • thisArg(可选):执行回调函数 callbackFnthis 被指向的对象。
javascript 复制代码
let arr4 = [1, 2, 3, 4, 5, 6, 7]
let res = arr4.some((item) => {
    return item > 5
})

console.log(res);

通过some判断数组中是否有数组,如果有则通过concat和解构结合的方法将其先解构再连接起来,数组先变成[1,2,3,4,[5]],然后变成[1,2,3,4,5],得出最终结果。

ini 复制代码
const arr = [1, 2, [3, 4, [5]] ];
function flatten(arr) {
   while (arr.some(item => Array.isArray(item))){
    arr = [].concat(...arr); // [1, 2, 3, 4, [5]]  --> [ 1, 2, 3, 4, 5 ]
   }
   return arr;
}

console.log(flatten(arr));

结语

如果你将这五种方法淡定的说出来,面试官一定被你拿下!嘿嘿~如果还有其他的方法的话,希望可以得到你们的分享哦,大家一起好好学习,天天向上!

相关推荐
别拿曾经看以后~8 分钟前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
我要洋人死11 分钟前
导航栏及下拉菜单的实现
前端·css·css3
川石课堂软件测试13 分钟前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
科技探秘人22 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人23 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR28 分钟前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香30 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q24985969333 分钟前
前端预览word、excel、ppt
前端·word·excel
小华同学ai38 分钟前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
problc43 分钟前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter