json树状结构的生成

数据库存储结构为平铺的结构:

[
{id:1 , parentId: 0, name: '', level: 0},
{id:2 , parentId: 0, name: '', level: 0},
{id:3 , parentId: 2, name: '', level: 1},
{id:4 , parentId: 2, name: '', level: 1},
{id:5 , parentId: 4, name: '', level: 2},
]


需要转换成树状结构:

{
	children:[
		{
			id: 1,
			name: ''
		},
		{
			id: 2,
			name: '',
			children: [
				{
					id: 3
				},
				{
					id: 4,
					children: [
						{
							id: 5
						}
					]
				}
			]
		},
	]
}

 

算法如下:

const setPath = (parent, arr) => {
  const children = arr.filter(item => item.parentId === parent.id);
  children.forEach((child, i) => {
    child.path = [ ...parent.path, i ];
    setPath(child, arr);
  });
  const myfn = path => {
    return path.map(p => `children[${p}]`).join('.');
  };
  const obj = {};

  return fn => {
    if (!fn) fn = myfn;
    arr = arr.filter(item => item.path !== undefined);
    arr.sort((a, b) => {
      return a.path.length - b.path.length;
    });
    arr.forEach(item => {
      _.set(obj, fn(item.path), item);
    });

    return obj;
  };
};


const res = yield dao.query({ solutionId }); // 从数据库拿到数据平铺的结构
generateMethod=undefined 一般情况下不用传生成方法
//如果有需要,比如只要二级结构,不需要到3级别,那么改变generateMethod即可
/*
generateMethod = path => {
      if (path.length === 2) return 'nouse';
      return path.map(p => `children[${p}]`).join('.');
}
*/
const tree = setPath({ id: 0, path: [] }, res)(generateMethod);

树既然生成了,如何通过给定的叶子节点拿到剪修过的树。树的分支只包含到给定的叶子,其余的分支修剪掉。

const shake = (tree, fn) => {
  const arr = [];
  const path = [];
  const a = {};
  function find(node, path) {
    if (node.children) {
      node.children.forEach((child, i) => find(child, [ ...path, i ]));
    } else {
      if (fn(node)) {
        arr.push(path);
      }
    }
  }
  function deleteNullNode(tree) {
    if (tree.children) {
      tree.children = tree.children.filter(c => c);
      tree.children.forEach(c => deleteNullNode(c));
    }
  }
  find(tree, path);
  arr.forEach(p => {
    for (let i = 1; i <= p.length; i++) {
      const _p = p.slice(0, i).map(c => `children[${c}]`).join('.');
      if (_.has(a, _p)) {
        continue;
      }
      _.set(a, _p, _.omit(_.get(tree, _p), 'children'));
    }
  });
  deleteNullNode(a);
  return a;
};

使用:

shake(tree, leaf => leaf.id == 5 )

 

算法还有很多改进的地方,有些内置的处理需要抽象。后续再更新。

转载于:https://my.oschina.net/u/867090/blog/1570936

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值