面试常考(干货满满):数字扁平化的五种方法
数组扁平化
数组的扁平化是面试常问的问题。
//让该数组转换为一维数组
let arr = [1, 2, [3, 4, [5, 6, [7, 8, 9]]]]
数组的flat()方法
flat方法介绍
数组的flat
方法用于将嵌套的数组“拉平”,变成一维数组。该方法返回一个新数组,对原数据没有影响。
语法:
arr.flat(depth)
其中,arr
是要进行扁平化处理的数组,depth
是可选参数,用于指定扁平化的深度。如果不指定depth
参数,flat
方法将默认展开一层嵌套的数组。如果depth
参数的值为Infinity
,则表示不论嵌套多少层都要展开。
代码实现
function flatten(arr) {
return arr.flat(Infinity)
}
递归
递归思想
eg:用递归实现6的阶乘。
方法:
- 找到公式:fun(n)=n * fun(n-1)
- 找到出口:当n为1时停止。如果不停止会一直递归下去,直到调用栈满。
function fun(n) {
if (n == 1) {
return 1
} else {
return n * fun(n - 1)
}
}
第一次运行fun函数:return 6*fun(5)
第二次运行fun函数:return 5*fun(4)
第三次运行fun函数:return 4*fun(3)
第四次运行fun函数:return 3*fun(2)
第五次运行fun函数:return 2*fun(1)
第六次运行fun函数:return 1
我们通过调用栈理解:
前五次运行的代码返回值都在等待下一次代码运行的返回值,直到第六次运行的代码返回值是1,则依次将返回值返回并且进行运算。
第一次运行fun函数得到的返回值是:6 * 5 * 4 * 3 * 2 * 1
第二次运行fun函数得到的返回值是:5 * 4 * 3 * 2 * 1
第三次运行fun函数得到的返回值是:4 * 3 * 2 * 1
第四次运行fun函数得到的返回值是:3 * 2 * 1
第五次运行fun函数得到的返回值是:2 * 1
第六次运行fun函数得到的返回值是:1
第一次运行的代码是等待时间最久的,其返回值是最终结果。
思路
递归思想:
- 创建一个结果数组res。
- 依次遍历数组:
- 如果所遍历到的数组元素的类型不是数组,则放入结果数组中。
- 如果所遍历到的数组元素的类型是数组,则在该数组元素内重复步骤1、步骤2和步骤3(也就是递归),并且对res和递归返回的数组进行拼接。
- 返回结果数组res(递归结束)。
方法:
- 找公式:
res = [...res, ...flatten(arr[i])]
或res = res.concat(flatten(arr[i]))
- 找出口:数组的元素没有是数组类型的时候。
具体流程:
第一次执行flatten函数:return res=[1,2,flatten(arr[i])]
第二次执行flatten函数:return res=[3,4,flatten(arr[i])]
第三次执行flatten函数:return res=[5,6,flatten(arr[i])]
第四次执行flatten函数:return res=[7,8,9]
到第四次结束递归,依次返回返回值得res=[1,2,3,4,5,6,7,8,9]
数组合并的方法
方法一:数组的concat()
方法。
数组的concat
方法用于连接两个或多个数组,并返回一个新的数组。该方法不会修改原始数组,而是返回一个新的数组,该数组是通过将所有参数添加到原始数组中生成的。
语法:
array.concat(value1,…,valueN)
其中,array
是要进行连接操作的数组,value1
、value2
等是要连接的数组或值。可以传递一个或多个参数。
方法二:数组的解构。
数组的解构语法是一种快速为变量赋值的简洁语法,它允许将数组的单元值快速批量赋值给一系列变量。
eg:....arr
可以表示arr数组内是所有元素。
let arr = [1, 2, 3, 4, 5];
console.log(...arr); // 1 2 3 4 5
eg:通过数组的结构进行合并数组
let arr = [1, 2, 3, 4, 5];
let arr1 =[6,7]
let newArr =[...arr,...arr1]
console.log(newArr); //[ 1, 2, 3, 4, 5 ,6,7]
代码实现
function flatten(arr) {
let res = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
// res = res.concat(flatten(arr[i]))
res = [...res, ...flatten(arr[i])]
} else {
res.push(arr[i])
}
}
return res;
}
数组的reduce()方法(递归思想)
reduce()方法介绍
reduce()
方法是 JavaScript 数组的一个迭代方法。
语法:
array.reduce(callbackFn, initialValue);
//callbackFn是回调函数
array.reduce((accumulator,currentValue,currentIndex,array)=>{
},initialValue);
参数声明(reduce方法有2个参数,reduce方法的回调函数参数有4个参数):
- callbackFn:执行数组中每个值的函数,包含四个参数:
accumulator
:累计回调函数的返回值;它是上一次调用回调函数的结果或者初始值(如果没有提供初始值,则数组的第一个元素作为初始值)。currentValue
:当前被处理的数组元素。currentIndex
(可选):当前元素在数组中的索引位置。可选参数。array
(可选):调用了reduce()
方法的数组本身。可选参数。
- initialValue(可选):作为第一次调用
callbackFn
函数时accumulator
的值。如果省略此参数,那么accumulator
的初始值为数组的第一个元素,currentValue
从数组的第二个元素开始。
eg:数组求和
let numbers = [1, 2, 3, 4];
let sum = numbers.reduce((accumulator, currentValue) => {
accumulator + currentValue
};
console.log(sum); // 输出:10
代码实现
function flatten(arr) {
return arr.reduce((prev, item) => {
return prev.concat(Array.isArray(item) ? flatten(item) : item)
}, [])
}
//或
function flatten(arr) {
return arr.reduce((prev, item) => {
if (Array.isArray(item)) {
return prev.concat(flatten(item))
} else {
return prev.concat(item)
}
}, [])
}
解析(也是递归思想):
- 使用
reduce
方法对输入的数组进行迭代处理: - 对于每个元素,判断它是否为数组。如果是,就继续递归调用
flatten
函数来处理该子数组,并将递归得到的结果与当前累积结果(prev
)进行连接;如果不是数组,就直接将该元素与累积结果进行连接。
数组的解构
some方法介绍
some()
方法是 JavaScript 数组的一个测试方法,用于检测数组中是否有元素满足指定的测试函数。它会依次执行数组每个元素上的测试函数,直到找到一个使得测试函数返回true的元素,此时 some()
立即停止遍历,并返回true。如果没有任何元素满足测试函数,some()
返回false。
语法:
array.some(callbackFn,thisArg);
//callbackFn是回调函数
array.some((element,index,array)=>{
},thisArg)
参数:
- callbackFn:数组中每个元素需要调用的函数。该函数接收三个参数:
element
:当前遍历的元素。index
:当前元素的索引位置。array
:调用some()
方法的数组本身。
- thisArg(可选):执行回调函数
callbackFn
时this
的值。
eg:检查数组中是否存在偶数。
let numbers = [1, 3, 5, 8, 9];
let hasEven = numbers.some((value) => value % 2 === 0);
console.log(hasEven); // 输出:true
思路
通过while循环使用some()
方法判断数组是否存在数组类型的元素:
如果存在就通过数组的解构将数组内的元素取出进行拼接,循环直到该数组的元素没有数组类型为止才结束。
代码实现
function flatten(arr) {
while (arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr;
}
toString()方法(有缺陷)
toString方法
eg:
当数组调用toString()
方法时,JavaScript会把数组中的每个元素转换成字符串(如果元素本身不是字符串的话),然后把这些字符串连接起来,中间以逗号,
分隔,最后返回一个由所有元素字符串组成的单一字符串。
eg:
console.log([1,2,3,4].toString)//'1,,2,3,4'
思路
- 通过toString方法将数组的中的每给元素转换成字符串,在通过字符串的
split(',')
方法将字符串转换为数组; - 通过遍历将数组的子元素通过
Number()
转换为数值。
代码实现
function flatten(arr) {
let str = arr.toString();
console.log(str);
let newArr = str.split(',').map((item) => Number(item));
return newArr;
}
缺点
只对全为数字的数组有效。
eg:[1, 'abc', 2, [3, 4, [5, 6, [7, 8, 9]]]]
let arr = [1, 'abc', 2, [3, 4, [5, 6, [7, 8, 9]]]]
function flatten(arr) {
let str = arr.toString();
console.log(str);
let newArr = str.split(',').map((item) => Number(item));
return newArr;
}
console.log(flatten(arr));
Number('abc')会转换为NaN。所以该方法只对全为数字的数组有效。
转载自:https://juejin.cn/post/7371053962069213196