数据扁平化的介绍及使用

目录

什么是数据扁平化?

下面是对其好处使用的举例:

文件目录的查找:

排序:

Array.prototype.flat:

其他方法实现数据扁平化:

扩展运算符 (...) 和递归

 使用栈(Stack)

总结:

什么是数据扁平化?

JS数据扁平化是指将一个多层嵌套的数组  转换为 一个一维数组的过程。在多层嵌套的数组中,元素可以是基本数据类型,也可以是数组,这种层层嵌套的结构使得数组的处理变得复杂。通过扁平化数组,可以简化数组操作和处理。

简单来讲就是:

他是一个数据处理的过程步骤,通常用于将嵌套的数据结构(如嵌套数组或对象)转换非嵌套(或“扁平”)结构。这个过程在编程中很常见。

JS数据扁平化的好处主要有以下几点

  1. 简化数据结构:在处理递归结构或者进行某些操作时(如遍历、查找、排序等),使用一维数组往往比使用多维数组更为方便和直观。。
  2. 优化性能:在某些场景下,如前端开发中处理递归的组件结构或嵌套的API响应数据时,使用扁平化后的数组可以提高性能,减少不必要的计算量

下面是对其好处使用的举例:

就举几个简单的例子吧。

文件目录的查找:

假设你有一个表示目录结构的嵌套数组,每个目录可能包含子目录和文件。如果你需要遍历所有文件或进行某种全局搜索,嵌套数组的结构可能会让这个过程变得复杂。通过将嵌套数组扁平化为一维数组,你可以更容易地访问和操作所有的文件。

下面这个使用了递归注意的是,对于非常大的数组或多层嵌套的数组,递归可能导致堆栈溢出

let nestedDirs = [  
  { name: '文件目录1', children: [{ name: '文件1' }, { name: '文件2' }] },  
  { name: '文件目录2', children: [{ name: '文件目录2-1', children: [{ name: '文件3' }] }] }  
];  
  
// 假设这是一个将嵌套目录结构扁平化为文件列表的函数(这里简化处理)  
function flattenFiles(dirs) {  
  let files = [];  
  dirs.forEach(dir => {  
    if (dir.children) {  
      files = files.concat(flattenFiles(dir.children));  
    } else {  
      files.push(dir.name);  
    }  
  });  
  return files;  
}  
  
let flatFiles = flattenFiles(nestedDirs);  
console.log(flatFiles); // ['文件1', '文件2', '文件3']
排序:

当你需要将一个数组中的元素进行排序去重或进行其他数组操作时,如果数组是嵌套的,那么你可能需要编写更复杂的逻辑来处理这些操作。而扁平化后的数组则可以直接使用JavaScript的内置数组方法来轻松完成这些操作。

Array.prototype.flat

(这个方法是非常推荐的)

语法:

可以参考MDN

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

Array.prototype.flatES6新增的一个数组方法,它的作用就是用来数组扁平化,并且根据传入的参数来决定展开的层级,Infinity表示完全展开如果要展开元素,则它们必须是数组

flat() 方法创建一个新的数组,并根据指定深度递归将所有子数组元素拼接新的数组中。

意思就是:

它不会改变 this 数组,而是返回一个浅拷贝,该浅拷贝包含了原始数组中相同的元素。

像这种简单的,其实也可以用 toString()+split(',') 实现,意思就不用说了吧

let nestedArray = [1, [6, 3], [4, [5, 8]], 7];
// 使用 flat 方法进行扁平化  
let flatArray = nestedArray.flat(Infinity); 
// 对扁平化后的数组进行排序  
flatArray.sort((a, b) => a - b); 
console.log(flatArray); // [1, 3, 4, 5, 6, 7, 8]

其他方法实现数据扁平化:

扩展运算符 (...) 和递归

结合扩展运算符递归实现扁平化。这种方法在函数式编程中很常见。

function flatten(array) {  
  return array.reduce((flat, toFlatten) => {  
    return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);  
  }, []);  
}  
  
// 或者使用更简洁的递归方式  
function flattenDeep(arr) {  
  return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);  
}  
  
const nestedArray = [1, [2, 3], [4, [5, 6]]];  
const flatArray = flattenDeep(nestedArray);  
console.log(flatArray); // [1, 2, 3, 4, 5, 6]

 使用栈(Stack)

处理大型嵌套数组时,使用栈可以避免递归调用栈过深的问题。

使用栈(Stack)来实现数组扁平化时,实际上并没有直接展示一个显式的栈数据结构(如 Array 用于模拟栈)

显式的栈或队列数据结构在多种编程语境中都存在,特别是在那些提供标准库或内置数据结构的编程语言中。

在栈的数据结构中,我们通常有两个基本操作:push(压栈)和pop(弹栈)。但在数组扁平化的场景中,我们其实是在模拟一个后进先出(LIFO)的队列,因为我们总是从嵌套数组的末尾开始处理,并将内部的数组元素推入“待处理”的数组中。

数组提供了 push 和 pop 方法来模拟栈的操作,但在这个特定的扁平化场景中,我们更多地是使用 concatreduce 或扩展运算符来模拟“推入”和“弹出”的行为。

        // 创建一个空数组来模拟栈,并将初始数组的元素作为栈的底部元素(实际上由于push操作,它们会成为栈顶元素)  
    const stack = [1, [2, 3], [4, [5, 6]]]; // 使用扩展运算符将数组元素放入栈中  
    const result = []; // 用于存储扁平化后的结果
  
    // 当栈不为空时,循环处理  
    while (stack.length > 0) {  
        // 弹出栈顶元素(即待处理的数组或值)  
        const current = stack.pop();  
  
        // 判断当前元素是否为数组  
        if (Array.isArray(current)) {  
            // 如果是数组,将其元素依次推入栈中(使用push保持后进先出的顺序)  
            stack.push(...current); // 相当于将数组元素逆序压入栈中,但因为后续pop操作,处理顺序仍然是正确的  
        } else {  
            // 如果不是数组,则直接添加到结果数组中  
            result.unshift(current); // 将非数组元素添加到结果数组中  
        }  
    }  
  
    // 返回扁平化后的结果数组  
    console.log(result,'result');

总结:

flat() 方法 通常最简单且性能最好的选择。

如果你需要处理更复杂的扁平化逻辑(如过滤掉某些元素),那么 reduce() 方法可能更适合。

如果你需要处理大型嵌套数组且担心递归调用栈溢出,那么栈的方法可能是最佳选择

  • 27
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

じòぴé南冸じょうげん

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

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

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

打赏作者

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

抵扣说明:

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

余额充值