面试中知多少?--数组、对象扁平化

95 阅读2分钟

一、数组的扁平化

1. 使用 flat() 方法

Array.prototype.flat() 方法可以将多维数组转化为一维数组。flat() 方法的一个显著特点是,它支持指定扁平化的深度,默认为 1。

let arr = [1, [2, [3, [4]]]];
let flattenedArr = arr.flat(2);  // 扁平化到深度 2
console.log(flattenedArr);  // [1, 2, 3, 4]

// console.log(arr.flat(Infinity));  //如果不确定有多少层,可以填Infinity

2. 使用递归实现数组扁平化

当我们需要扁平化深度不确定的数组时,递归是一种非常实用的方法。通过递归处理每个数组元素,直到它不是数组为止。

function flatten(arr) {
  let result = [];
  
  for (let item of arr) {
    if (Array.isArray(item)) {
      result.push(...flatten(item));  // 递归处理数组
    } else {
      result.push(item);  // 非数组元素直接添加到结果中
    }
  }

  return result;
}

let arr = [1, {a: 1}, [2, [3, 4]]];
console.log(flatten(arr));  // [1, {a: 1}, 2, 3, 4]

3. 使用 toString() 方法

通过 toString() 方法将数组转换为字符串后,再通过 split() 方法分割成数组,得到一个一维数组。这种方法对于只有原始类型数据的数组有效。

let arr = [1, [2, [3, 4]]];
let flattenedArr = arr.toString().split(',').map(Number);  // 转为字符串,再分割并转为数字
console.log(flattenedArr);  // [1, 2, 3, 4]

4. 使用 while 循环和 concat() 方法

通过 while 循环判断数组中是否存在嵌套的数组,如果存在,则通过 concat() 方法展开数组直到没有嵌套数组为止。

function flatten2(arr) {
  while (arr.some(item => Array.isArray(item))) {
    arr = [].concat(...arr);  // 展开数组
  }
  return arr;
}

let arr = [1, [2, [3, 4]]];
console.log(flatten2(arr));  // [1, 2, 3, 4]

二、对象的扁平化

1. 递归实现对象的扁平化

通过递归的方式处理嵌套对象的每个键值对,最终生成一个包含所有嵌套路径的扁平化对象。

let obj = {
  a: 1,
  b: [1, 2, {c: 3}, [4]],
  d: {
    e: 2,
    f: 3
  },
  g: null
};

function flatObj(target) {
  let res = {};

  function help(target, oldKey) {
    for (let key in target) {
      let newKey;
      if (oldKey) {  // 递归时,构造新的键名
        if (Array.isArray(target)) {
          newKey = `${oldKey}[${key}]`;  // 数组的键名如 'b[2]'
        } else {
          newKey = `${oldKey}.${key}`;  // 对象的键名如 'b.2'
        }
      } else {
        newKey = key;  // 最初的键名
      }

      if (Object.prototype.toString.call(target[key]) === '[object Object]' || Array.isArray(target[key])) {
        help(target[key], newKey);  // 递归处理嵌套对象或数组
      } else {
        res[newKey] = target[key];  // 将最终结果添加到结果对象中
      }
    }
  }

  help(target, '');  // 初始递归

  return res;
}

console.log(flatObj(obj));

输出结果

{
  'a': 1,
  'b[0]': 1,
  'b[1]': 2,
  'b[2].c': 3,
  'b[3][0]': 4,
  'd.e': 2,
  'd.f': 3
}