js/vue/react 如何转换这种树形结构(可能有点复杂)

image
如图所示,这树形结构目前对应的代码是↓

const data = [{
        name: '桑椹',
        id: '114'
      }, {
        name: '黑莓',
        id: '115'
      }, {
        name: '柑橘类',
        id: '116',
        children: [{
          name: '橘子',
          id: '117'
        }, {
          name: '橙子',
          id: '118'
        }]
      },
      {
        name: '奥特曼大全',
        id: '119',
        children: [{
          name: '昭和类',
          id: '120',
          children: [{
            name: '杰克',
            id: '121'
          }, {
            name: '泰罗',
            id: '122'
          }, {
            name: '艾斯',
            id: '123'
          }]
        }, {
          name: '平成类',
          id: '124',
          children: [{
            name: '迪迦',
            id: '125'
          }, {
            name: '盖亚',
            id: '126'
          }]
        }]
      }]

我需要的效果是,如果没有父级,那就放进一个对象里,如果有子级,那就判断有几个子级,也就是children里面还有没有children,如果有,那就也一起放入那个对象里,如果只有一层children,同样的这一层children也放入那个对象里。

理想输出效果↓

let data = [{
          name: '草莓',
          id: '113'
        }, {
          name: '桑椹',
          id: '114'
        }, {
          name: '黑莓',
          id: '115'
        }, {
          name: '橘子',
          id: '117'
        }, {
          name: '橙子',
          id: '118'
        }, {
          name: '杰克',
          id: '121'
        }, {
          name: '泰罗',
          id: '122'
        }, {
          name: '艾斯',
          id: '123'
        }, {
          name: '迪迦',
          id: '125'
        }, {
          name: '盖亚',
          id: '126'
        }]

图示意↓
image
难点在于,桑葚和黑莓是没有父级子级的,而有的有一层父级(如橘子、橙子)、有的有两层父级,所以用

data.map(item => item.children.map(child => child.children)).flat(Infinity)

这段代码是没有用的,我该怎么操作呢~!

在这里先谢谢各位大神大哥们的解答,小弟感激不尽!

感谢@zangeci @gentlecoder945两位大神的解答,但是你们的代码我试了一下都有这个问题
image
橘子和橙子都重复了,请问下该怎么解决呢

阅读 2.3k
3 个回答

递归,这种问题第一直觉一般就是递归

var data = [{
        name: '桑椹',
        id: '114'
      }, {
        name: '黑莓',
        id: '115'
      }, {
        name: '柑橘类',
        id: '116',
        children: [{
          name: '橘子',
          id: '117'
        }, {
          name: '橙子',
          id: '118'
        }]
      },
      {
        name: '奥特曼大全',
        id: '119',
        children: [{
          name: '昭和类',
          id: '120',
          children: [{
            name: '杰克',
            id: '121'
          }, {
            name: '泰罗',
            id: '122'
          }, {
            name: '艾斯',
            id: '123'
          }]
        }, {
          name: '平成类',
          id: '124',
          children: [{
            name: '迪迦',
            id: '125'
          }, {
            name: '盖亚',
            id: '126'
          }]
        }]
      }]

function mapLastChild(list) {
  return list.reduce((res, item) => {
    if(item.children) res = res.concat(mapLastChild(item.children))
    else res.push(item);
    return res;
  }, []);
}

mapLastChild(data)
const flatTree = (list) =>
  list.reduce((acc, cur) => {
    if (!cur.children) {
      acc.push(cur)
      return acc
    } else {
      return acc.concat(flatTree(cur.children))
    }
  }, [])

一个问题三个踩,也是6,估计很多大佬看到这种日经题就烦,同样惹人厌的可能还有千篇一律的异步顺序题。
这题我看干脆用正则得了:

const { parse } = JSON;
JSON.stringify(data).match(/(\{"name":"[^"]+","id":"[^"]+"\})|("id":"[^"]+"\},\{"name":"[^"]+")/g).map(parse);

一行代码搞定。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题