将Javascript树对象转换为另一个树对象

时间:2020-04-22 22:30:01

标签: javascript

我有一个看起来像这样的树对象:

let treeArray = [{
  id: 'x/y/z',
  status: 'Not Ready',
  application: 'x',
  artifactID: 'z',
  parent: 'None',
  children: [{
    id: 'a/b/c',
    status: 'Not Ready',
    application: 'a',
    artifactID: 'c',
    parent: 'x/y/z',
    children: [{
      id: 'p/q/r',
      status: 'Not Ready',
      application: 'p',
      artifactID: 'r',
      parent: 'a/b/c',
      children: []
    }]
  }]
}]

我需要将其转换为以下内容:

let result = 
  [ { id: 1, target: 'x', status: 'Not Ready'} 
  , { id: 2, target: 'z', status: 'Not Ready', parentID: 1 } 
  , { id: 3, target: 'a', status: 'Not Ready', parentID: 2 } 
  , { id: 4, target: 'c', status: 'Not Ready', parentID: 3 }
  , { id: 5, target: 'p', status: 'Not Ready', parentID: 4 } 
  , { id: 6, target: 'r', status: 'Not Ready', parentID: 5 } 
  ] 

请实现这一目标的最佳方法是什么?

编辑:所需的格式已更改。请注意,子级中可以有任意多个元素。这里我的孩子只有一个元素。

4 个答案:

答案 0 :(得分:1)

这似乎是递归函数的完美应用,因此它可以在需要的任何子级上运行。

基本上,对于树的每个元素,您都构建展平的版本,然后如果它有子代,则在子代上调用相同的函数,以便以完全相同的方式解析它们并将它们添加到数组中。

我使用了嵌套函数,以便在数组上调用该函数会返回一个新数组,而无需修改原始数组,也不需要全局变量。

我从问题中的结果中修改的一件事是,我在所有元素上都包含了parent属性,但是如果没有父级,则使它返回null,这使其功能和值非常明确,这有助于您计划进一步处理从任何函数返回的数组。任何数字都是错误的,因为该ID号没有父项,而省略它会使结构可变。

const expandTree = tree => {
  let id = 0;
  const flattened = [];

  const expandBranch = (tree, parentId) => {
      tree.forEach(branch => {
        id ++;
        flattened.push({
            id: id,
            target: branch.id[0],
            status: branch.status,
            parentID: parentId,
          })
        if (branch.children.length > 0) {
          expandBranch(branch.children, id)
        }
      }
    )
  };
  expandBranch(tree, null);
  return flattened;
};

优点是它仍然可以在树的任何分支上的任何数量的孩子中使用:

const treeArray = [{
  id: 'x/y/z',
  status: 'Not Ready',
  application: 'x',
  artifactID: 'z',
  parent: 'None',
  children: [{
    id: 'a/b/c',
    status: 'Not Ready',
    application: 'a',
    artifactID: 'c',
    parent: 'x/y/z',
    children: [{
      id: 'p/q/r',
      status: 'Not Ready',
      application: 'p',
      artifactID: 'r',
      parent: 'a/b/c',
      children: []
    }]
  }]
},
{
  id: 'x/y/z',
  status: 'Not Ready',
  application: 'x',
  artifactID: 'z',
  parent: 'None',
  children: [{
    id: 'a/b/c',
    status: 'Not Ready',
    application: 'a',
    artifactID: 'c',
    parent: 'x/y/z',
    children: [{
      id: 'p/q/r',
      status: 'Not Ready',
      application: 'p',
      artifactID: 'r',
      parent: 'a/b/c',
      children: [{
        id: 'p/q/r',
        status: 'Not Ready',
        application: 'p',
        artifactID: 'r',
        parent: 'a/b/c',
        children: []
      },{
        id: 'p/q/r',
        status: 'Not Ready',
        application: 'p',
        artifactID: 'r',
        parent: 'a/b/c',
        children: []
      },{
        id: 'p/q/r',
        status: 'Not Ready',
        application: 'p',
        artifactID: 'r',
        parent: 'a/b/c',
        children: []
      }
      ]
    }]
  }]
}]

const expandTree = tree => {
  let id = 0;
  const flattened = [];

  const expandBranch = (tree, parentId) => {
      tree.forEach(branch => {
        id ++;
        flattened.push({
            id: id,
            target: branch.id[0],
            status: branch.status,
            parentID: parentId,
          })
        if (branch.children.length > 0) {
          expandBranch(branch.children, id)
        }
      }
    )
  };
  expandBranch(tree, null);
  return flattened;
};

console.log(expandTree(treeArray))

答案 1 :(得分:0)

这是一个简单的递归问题

const treeArray = 
  [ { id: 'x/y/z', status: 'Not Ready', application: 'x', artifactID: 'z', parent: 'None', children: 
      [ { id: 'a/b/c', status: 'Not Ready', application: 'a', artifactID: 'c', parent: 'x/y/z', children: 
          [ { id: 'p/q/r', status: 'Not Ready', application: 'p', artifactID: 'r', parent: 'a/b/c', children: [] } 
  ] } ] } ] 
  ;
let result = []
  , count  = 0
  ;
function addResultRows( elm, key )
  {
  elm.forEach(elm=>
    {
    newItem = { id: ++count, target: elm.application, status: elm.status }
    if (key > 0 ) newItem.parentId = key
    result.push(newItem)
    if ( elm.children.length > 0)
      {
      addResultRows( elm.children, newItem.id ) 
      }
    })
  }
addResultRows( treeArray, 0 )
  ;
console.log( JSON.stringify( result ,0, 2)  )
  ;

答案 2 :(得分:-1)

text = font.render('COOKIES : ' + str(score) + '/' + str(winValue), True, BLACK, WHITE)

答案 3 :(得分:-1)

let counter = 1;
function flatit(arr, parent) {
    let arrResult = [];

    arr.forEach(el => {
        let newEl = {
            id: counter,
            target: el.application,
            status: el.status
        };

        if (parent) newEl.parent = parent;
        arrResult.push(newEl);        
        if (el.children) flatit(el.children, counter++).forEach(elc => arrResult.push(elc));
    });

    return arrResult;
}

console.log(flatit(treeArray));

结果:

[
  { id: 1, status: 'Not Ready', target: 'x' },
  { id: 2, status: 'Not Ready', target: 'a', parentID: 1 },
  { id: 3, status: 'Not Ready', target: 'p', parentID: 2 }
]