持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

前言

这是一道工作中常用到的算法题~

你能学到

JS 基础! | 扁平数组和JSON树的转换 - 图1

扁平数组 -> JSON 树

需求

你可能会得到类似这样的一个扁平数组,数组中的每一项都是一个对象,对象中有相关的逻辑结构的属性值~

  1. let flatArr = [
  2. { id: 1, title: "title1", parent_id: 0 },
  3. { id: 2, title: "title2", parent_id: 0 },
  4. { id: 3, title: "title2-1", parent_id: 2 },
  5. { id: 4, title: "title3-1", parent_id: 3 },
  6. { id: 5, title: "title4-1", parent_id: 4 },
  7. { id: 6, title: "title3-2", parent_id: 3 },
  8. ];

效果

你需要的是根据其中的逻辑,获得一个 合理 的JSON树,其中的串联关系就要根据逻辑建立~
主要看那个parent_id
image.png

实现

结果数组

JSON 树形式,其实也是数组~

  1. const result = [];

数组->map

先把数组转为 mapid作为 key,本身作为 value, 后面遍历匹配时就要靠这个 map里的 id

  1. const map = arr.reduce((pre, cur) => {
  2. // key 就是 id,即 cur.id; value 为值本身
  3. pre[cur.id] = cur;
  4. return pre;
  5. }, {}); // 传入初始值为 空对象{}

这里的 arr 是外面一层函数传入的参数,等下还要封装的

ok,我们现在就拿到了扁平数组的 map 形式
image.png

vscode 中查看代码运行

关于这个在 vscode 中查看代码运行的插件可以看这篇文章:vscode插件—— Quokka.js的简单使用

遍历 数组

使用 for of遍历数组。

  • 父元素id为 0 的,那么就可以直接 push到第一层,不需要其他的处理
  • 其余的就要找到对应的父元素,并push到父元素之下
    1. for (let item of arr) {
    2. // 先找到父元素为 0 的,那么就可以直接 push 到第一层,不需要其他的处理
    3. if (item.parent_id === 0) {
    4. result.push(item);
    5. continue;
    6. }
    7. // 对于不是第一层的,我们就要先找到其父元素
    8. if (item.parent_id in map) {
    9. const parent = map[item.parent_id];
    10. (parent.children || (parent.children = [])).push(item); //这个简洁的方法
    11. }
    12. }

    简洁初始化并操作

    这个方法是我看源码的时候学的~

    从mitt、tiny-emitter源码中学习手写订阅发布


全貌

ok,封装到函数中,并返回结果即可

  1. const flatArrToJSONTree = arr => {
  2. const result = [];
  3. const map = arr.reduce((pre, cur) => {
  4. pre[cur.id] = cur;
  5. return pre;
  6. }, {});
  7. for (let item of arr) {
  8. if (item.parent_id === 0) {
  9. result.push(item);
  10. continue;
  11. }
  12. if (item.parent_id in map) {
  13. const parent = map[item.parent_id];
  14. (parent.children || (parent.children = [])).push(item);
  15. }
  16. }
  17. return result;
  18. };

测试

插件数组中对象无法展开,所以赋值到控制台看看

  1. const res = flatArrToJSONTree(flatArr);
  2. console.log(res)

image.png


JSON 树 -> 扁平数组

需求

ok,除了上面的需求,有时我们可能也需要将 一个 JSON树形式的数组扁平化

效果

  1. const res2 = JSONTreeToFlatArr(res);

image.png

实现

相比 数组转换为 JSON 树,JSON树转化为数组的代码量就少了很多,这里就不分段细说了

  1. const JSONTreeToFlatArr = tree => {
  2. return tree.reduce((pre, cur) => {
  3. //解构拿出属性,并给 children 一个默认值
  4. const { children = [], ...rest } = cur;
  5. // concat 将每次结果都进行拼接
  6. return pre.concat([{ ...rest }], JSONTreeToFlatArr(children)); //递归处理 children
  7. }, []);
  8. };

也是利用 reduce 这个方法,发现这个方法真是好用啊~
concat 拼接数组,再在里面递归处理~

测试

  1. const res2 = JSONTreeToFlatArr(res);
  2. console.log(res2);

image.png
大功告成~

学习资源