从扁平数组创建树结构数组

时间:2021-06-03 16:45:40

标签: javascript arrays loops sorting treeview

我有一个像这样的扁平阵列

const arr = 
  [ { org_level_code: 'BBI',   org_level_name: 'Bostwick',     org_level_parent_code: 'toplevel',      children: null } 
  , { org_level_code: 'CDI',   org_level_name: 'BBi US',       org_level_parent_code: 'BBI',           children: null } 
  , { org_level_code: '60',    org_level_name: '60 - Sidney1', org_level_parent_code: 'BBI/CDI',       children: null } 
  , { org_level_code: 'BBC',   org_level_name: 'BBi Canada',   org_level_parent_code: 'BBI/CDI',       children: null } 
  , { org_level_code: 'BBI-2', org_level_name: 'BBi U.S. ',    org_level_parent_code: 'BBI/CDI',       children: null } 
  , { org_level_code: 'DEPT',  org_level_name: 'Dept',         org_level_parent_code: 'BBI/CDI/BBI-2', children: null } 
  ]

从这个数组我需要这样的数组

const data = 
  [ { org_level_code: 'BBI',              org_level_name: 'Bostwick',   org_level_parent_code: 'toplevel',     children: 
      [ { org_level_code: 'CDI',          org_level_name: 'BBi US',     org_level_parent_code: 'BBI',          children: 
          [ { org_level_code: 'BBC',      org_level_name: 'BBi Canada', org_level_parent_code: 'BBI/CDI',       children: null } 
          , { org_level_code: '60',    org_level_name: '60 - Sidney1',  org_level_parent_code: 'BBI/CDI',       children: null } 
          , { org_level_code: 'BBI-2',    org_level_name: 'BBi U.S. ',  org_level_parent_code: 'BBI/CDI',      children: 
              [ { org_level_code: 'DEPT', org_level_name: 'Dept',       org_level_parent_code: 'BBI/CDI/BBI-2', children: null }
  ] } ] } ] } ] 

正如您在示例中看到的,"org_level_parent_code": "toplevel" 是父节点,"org_level_parent_code": "BBI" 是父节点的第二个节点,因为第一个节点与子节点有 "org_level_code": "BBI" 和 {{1 }} 表示第三级。这些斜线分隔的字符串与它们各自的父节点有关系。

斜线分隔字符串的最后一个字符串例如 "org_level_parent_code": "BBI/CDI" 与上面的节点有关系。

注意-顶级节点可以是多个,如BBI-2

我真的很努力地实现这一目标。请帮忙。

3 个答案:

答案 0 :(得分:1)

您可以使用 Map 来存储节点位置,如果下一个节点找到父节点,则推送到该父节点。

const arr = [{ "org_level_code": "BBI", "org_level_name": "Bostwick", "org_level_parent_code": "toplevel", "children": null }, { "org_level_code": "BBI", "org_level_name": "BBi US", "org_level_parent_code": "BBI", "children": null }, { "org_level_code": "60", "org_level_name": "60 - Sidney1", "org_level_parent_code": "BBI/BBI", "children": null }, { "org_level_code": "BBC", "org_level_name": "BBi Canada", "org_level_parent_code": "BBI/BBI", "children": null }, { "org_level_code": "BBI-2", "org_level_name": "BBi U.S. ", "org_level_parent_code": "BBI/BBI", "children": null }, { "org_level_code": "DEPT", "org_level_name": "Dept", "org_level_parent_code": "BBI/BBI/BBI-2", "children": null }];

let map = new Map;
let result = arr.shift();
for (const item of arr) {
  item.children ??= []
  let parentId = item.org_level_parent_code;
  map.set(parentId + "/" + item.org_level_code, item);
  map.get(parentId)?.children.push(item);
}
result.children = [map.get("BBI/BBI")];

console.log(result);

答案 1 :(得分:-1)

我们可以根据级别添加节点。以下是解决方案:-

const orgGreenTree = (array) => {
let levels = [{}];
array.forEach(function(a) {
  let level;
  if (a.org_level_parent_code === 'toplevel') {
    level = 0;
  }
  else {
    level = (a.org_level_parent_code.match(/\//g) || []).length + 1;
  }
  levels.length = level + 1;
  // console.log(level)
  levels[level].children = levels[level].children || [];
  levels[level].children.push(a);
  levels[level + 1] = a;
});
 return levels[0].children;
};
console.log(orgGreenTree(array));

答案 2 :(得分:-1)

这是使用 Array#reduce() 的简洁、更通用的解决方案。

它累积成一个对象,其属性是每个项目的 children 数组的路径。顶级项目累积到 toplevel 子数组中,这是最终结果。

const
  arr = [{ org_level_code: 'BBI', org_level_name: 'Bostwick', org_level_parent_code: 'toplevel', children: null }, { org_level_code: 'CDI', org_level_name: 'BBi US', org_level_parent_code: 'BBI', children: null }, { org_level_code: '60', org_level_name: '60 - Sidney1', org_level_parent_code: 'BBI/CDI', children: null }, { org_level_code: 'BBC', org_level_name: 'BBi Canada', org_level_parent_code: 'BBI/CDI', children: null }, { org_level_code: 'BBI-2', org_level_name: 'BBi U.S. ', org_level_parent_code: 'BBI/CDI', children: null }, { org_level_code: 'DEPT', org_level_name: 'Dept', org_level_parent_code: 'BBI/CDI/BBI-2', children: null }],

  result = arr
    .reduce((acc, item) => {

      const parentCode = item.org_level_parent_code;
      const childrenPath = `${parentCode === 'toplevel' ? '' : parentCode + '/'}${item.org_level_code}`;

      acc[childrenPath] ??= [];
      (acc[parentCode] ??= []).push({ ...item, children: acc[childrenPath] })

      return acc;
    }, {})
    .toplevel

console.log(JSON.stringify(result, null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }

此解决方案不依赖于输入数组的顺序,即使尚未遇到父项也会正确累积子项。

const
  arr = [
    { org_level_code: 'DEPT', org_level_name: 'Dept', org_level_parent_code: 'BBI/CDI/BBI-2', children: null }
    , { org_level_code: 'CDI', org_level_name: 'BBi US', org_level_parent_code: 'BBI', children: null }
    , { org_level_code: '60', org_level_name: '60 - Sidney1', org_level_parent_code: 'BBI/CDI', children: null }
    , { org_level_code: 'BBI', org_level_name: 'Bostwick', org_level_parent_code: 'toplevel', children: null }
    , { org_level_code: 'BBC', org_level_name: 'BBi Canada', org_level_parent_code: 'BBI/CDI', children: null }
    , { org_level_code: 'BBI-2', org_level_name: 'BBi U.S. ', org_level_parent_code: 'BBI/CDI', children: null }
  ],

  result = arr
    .reduce((acc, item) => {

      const parentCode = item.org_level_parent_code;
      const childrenPath = `${parentCode === 'toplevel' ? '' : parentCode + '/'}${item.org_level_code}`;

      acc[childrenPath] ??= [];
      (acc[parentCode] ??= []).push({ ...item, children: acc[childrenPath] })

      return acc;
    }, {})
    .toplevel

console.log(JSON.stringify(result, null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }