前端扁平化数据转树形数据_前端面试题——数组扁平化(递归、迭代&generator)...

前端面试,五花八门。最近我又看到了一道题——数组扁平化。对于多层嵌套数组:[1, [2, [3, 4, [5]]]],要求转换为只有一层的数组:[1, 2, 3, 4, 5]

那么数组的扁平化究竟怎么实现呢?这篇文章介绍递归、迭代、generator三种方法。

递归

看到这道题目,最最直接的反应就是递归了:对于每个子元素,如果是数组的话,就递归调用这个子元素。先看代码:

function flatten(arr) {

if (!Array.isArray(arr)) {

return [arr];

}

let res = [];

for (let i=0;i

res.push(...flatten(arr[i]));

}

return res;

}

const arr = [1, [2, [3, 4, [5]]]];

console.log(flatten(arr))

写递归分三步:第一步:确定结束条件。在这个问题中,如果当前传入的元素arr不是数组的话,就包装成数组返回。如果是数组的话,才继续进行接下来的步骤。

第二步:对于每个子元素进行处理。我们创建一个叫做res的数组,对于每个子元素,都把它放进数组当中。而每个子元素都可能是数组,这里我们不需要判断子元素是不是数组,因为在结束条件中会自动判断。

第三步:返回值。这里只要返回res就可以。

运行程序,输出结果:[1, 2, 3, 4, 5]

迭代

对于把递归转换成迭代,很多情况下都需要一个stack来模拟函数调用。先看代码:

function flatten2(arr) {

const stack = [...arr];

const res = [];

while (stack.length) {

// 从栈里取出 const next = stack.pop();

if (Array.isArray(next)) {

// 把next扁平化,然后放入stack中 stack.push(...next);

} else {

res.push(next);

}

}

// reverse to restore input order return res.reverse();

}

console.log(flatten2(arr))

基本思想就是,先把arr中的东西都放入stack中,然后不停pop stack中的东西。如果pop出来的是一个数组,那么把数组扁平化,再放入stack中;如果pop出来的不是数组,那么放入res中。

运行程序,输出结果:[1, 2, 3, 4, 5]

generator

generator是ES6提供的一种异步编程解决方法。这里的generator方法的思想也是迭代的(当然前面我迭代的代码,可以把判断是否是array的条件放在if条件当中)

function* flatten3(arr) {

let length = arr.length;

for (let i=0; i

let item = arr[i];

if (Array.isArray(item)) {

yield* flatten3(item);

} else {

yield item;

}

}

}

let res = [];

for (let f of flatten3 (arr)) {

res.push(f);

}

console.log(res)

需要注意的是,调用flatten3 (arr)并不会直接得到结果,需要时用next()或者放在for循环中得到所有结果。

好啦,这就是数组扁平化的几种方法。希望大家面试一切顺利!顺便关注我的公众号:前端三剑客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设现有一个扁平化数据结构,其中每个节点包含id、parentId和name三个属性,表示该节点的唯一标识、父节点的唯一标识和节点名称。现在需要将这个扁平化数据结构换成树形数据结构。 可以使用递归方法来实现。具体步骤如下: 1. 定义一个递归函数,参数为当前节点的id和整个扁平化数据结构。 2. 在递归函数中,遍历整个扁平化数据结构,查找所有父节点为当前节点id的节点,并将这些节点作为当前节点的子节点。 3. 对于每个子节点,递归调用该函数,参数为子节点的id和整个扁平化数据结构。 4. 递归函数返回当前节点及其所有子节点构成的树形数据结构。 代码实现如下: ``` function flattenToTree(id, data) { var tree = {id: id, name: '', children: []}; for (var i = 0; i < data.length; i++) { if (data[i].parentId == id) { var child = {id: data[i].id, name: data[i].name, children: []}; tree.children.push(child); var subChildren = flattenToTree(data[i].id, data); if (subChildren.children.length > 0) { child.children = subChildren.children; } } } return tree; } ``` 调用该函数的示例代码如下: ``` var data = [ {id: 1, parentId: 0, name: 'A'}, {id: 2, parentId: 1, name: 'B'}, {id: 3, parentId: 1, name: 'C'}, {id: 4, parentId: 2, name: 'D'}, {id: 5, parentId: 2, name: 'E'}, {id: 6, parentId: 3, name: 'F'} ]; var tree = flattenToTree(1, data); console.log(tree); ``` 输出结果为: ``` { id: 1, name: '', children: [ { id: 2, name: 'B', children: [ {id: 4, name: 'D', children: []}, {id: 5, name: 'E', children: []} ] }, { id: 3, name: 'C', children: [ {id: 6, name: 'F', children: []} ] } ] } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值