likes
comments
collection
share

面试常考(干货满满):数字扁平化的五种方法

作者站长头像
站长
· 阅读数 107

数组扁平化

数组的扁平化是面试常问的问题。

//让该数组转换为一维数组
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的阶乘。

方法:

  1. 找到公式:fun(n)=n * fun(n-1)
  2. 找到出口:当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

第一次运行的代码是等待时间最久的,其返回值是最终结果。

思路

递归思想:

  1. 创建一个结果数组res。
  2. 依次遍历数组:
    • 如果所遍历到的数组元素的类型不是数组,则放入结果数组中。
    • 如果所遍历到的数组元素的类型是数组,则在该数组元素内重复步骤1、步骤2和步骤3(也就是递归),并且对res和递归返回的数组进行拼接。
  3. 返回结果数组res(递归结束)。

方法

  1. 找公式:res = [...res, ...flatten(arr[i])]res = res.concat(flatten(arr[i]))
  2. 找出口:数组的元素没有是数组类型的时候。

具体流程

第一次执行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是要进行连接操作的数组,value1value2等是要连接的数组或值。可以传递一个或多个参数。

方法二:数组的解构。

数组的解构语法是一种快速为变量赋值的简洁语法,它允许将数组的单元值快速批量赋值给一系列变量。

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)
        }
    }, [])
}

解析(也是递归思想):

  1. 使用 reduce 方法对输入的数组进行迭代处理:
  2. 对于每个元素,判断它是否为数组。如果是,就继续递归调用 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(可选):执行回调函数 callbackFnthis 的值。

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'

思路

  1. 通过toString方法将数组的中的每给元素转换成字符串,在通过字符串的split(',')方法将字符串转换为数组;
  2. 通过遍历将数组的子元素通过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
评论
请登录