【问题标题】:Need to convert array of objects that has parent child relationship and convert to primeng tree table nodes需要转换具有父子关系的对象数组并转换为primeng树表节点
【发布时间】:2018-10-12 15:19:22
【问题描述】:

给定具有父子关系的扁平化对象数组列表。我需要转换为素数 ng 树表数据结构。 我想一次展开所有的孩子。

我的最终目标是具有以下结构:

[{
        "data":{
            "name":"Pictures",
            "size":"150kb",
            "type":"Folder"
        },
        "children":[
            {
                "data":{
                    "name":"barcelona.jpg",
                    "size":"90kb",
                    "type":"Picture"
                }
            },
            {
                "data":{
                    "name":"primeui.png",
                    "size":"30kb",
                    "type":"Picture"
                }
            },
            {
                "data":{
                    "name":"optimus.jpg",
                    "size":"30kb",
                    "type":"Picture"
                }
            }
        ]
    }]

给定 json 数组:

 data = [
    {
        dataId: 1,
        name: test1,
        description: 'some desc',
        parentId: null
    },
    {
        dataId: 2,
        name: test1,
        description: 'some desc',
        parentId: 2
    },
    {
        dataId: 3,
        name: test1,
        description: 'some desc',
        parentId: 1
    },
    {
        dataId: 4,
        name: test1,
        description: 'some desc',
        parentId: null
    }
]

【问题讨论】:

  • 别担心,你很快就会得到很多答案..;)
  • 到目前为止你有什么尝试?

标签: angular recursion ecmascript-6 primeng treetable


【解决方案1】:

递归函数的解决方案

function getDataByParentId(data, parent) {
  const result = data
    .filter(d => d.parentId === parent);

  if (!result && !result.length) {
    return null;
  }

  return result.map(({ dataId, name, description }) => 
    ({ dataId, name, description, children: getDataByParentId(data, dataId) }))
}

const data = [{
    dataId: 1,
    name: 'test1',
    description: 'some desc',
    parentId: null
  },
  {
    dataId: 2,
    name: 'test2',
    description: 'some desc',
    parentId: 1
  },
  {
    dataId: 3,
    name: 'test3',
    description: 'some desc',
    parentId: 1
  },
  {
    dataId: 4,
    name: 'test4',
    description: 'some desc',
    parentId: null
  },
  {
    dataId: 5,
    name: 'test5',
    description: 'some desc',
    parentId: 4
  },
  {
    dataId: 6,
    name: 'test6',
    description: 'some desc',
    parentId: 5
  }
];

console.log(getDataByParentId(data, null));

【讨论】:

  • 这对我有用。我不得不稍微调整一下。谢谢。
  • 非常干净的解决方案。
【解决方案2】:

这是一个“滥用”filter 的可能解决方案。这个想法是首先构建一个从dataId 到节点的简单映射,然后在filter 迭代中使用它来构建树。

const data = [{
    dataId: 1,
    name: 'test1',
    description: 'some desc',
    parentId: null
  },
  {
    dataId: 2,
    name: 'test2',
    description: 'some desc',
    parentId: 1
  },
  {
    dataId: 3,
    name: 'test3',
    description: 'some desc',
    parentId: 1
  },
  {
    dataId: 4,
    name: 'test4',
    description: 'some desc',
    parentId: null
  },
  {
    dataId: 5,
    name: 'test5',
    description: 'some desc',
    parentId: 4
  },
  {
    dataId: 6,
    name: 'test6',
    description: 'some desc',
    parentId: 5
  }
];


let dataMap = data.reduce((m, d) => {
  m[d.dataId] = Object.assign({}, d);
  return m;
}, {});

const trees = data.filter(d => {
  if (d.parentId !== null) { // assign child to its parent
    let parentNode = dataMap[d.parentId];
    if (!('children' in parentNode)) parentNode['children'] = [];
    parentNode.children.push(dataMap[d.dataId]);
    return false;
  }
  return true; // root node, do nothing
}).map(d => dataMap[d.dataId]);

console.log(trees);

当然,您可以进一步调整,只从数据对象中提取某些属性。

【讨论】:

  • 你能帮我一个像下面这样的结构吗? “数据”:{“名称”:“到期”,“类型名称”:“联合”,},“孩子”:[{“数据”:{“名称”:空,“类型名称”:“空”,}} ]
【解决方案3】:

data = [
{
    dataId: 1,
    name: "test1",
    description: 'some desc',
    parentId: null
},
{
    dataId: 2,
    name: "test2",
    description: 'some desc',
    parentId: 1
},
{
    dataId: 3,
    name: "test3",
    description: 'some desc',
    parentId: 4
},
{
    dataId: 4,
    name: "test4",
    description: 'some desc',
    parentId: null
}
]

// find leaf who does not have child using recursive
function findLeaf(data, curIndex, parIndex) {
    const childId = data[curIndex].dataId;
    for(let i = 0; i < data.length; i++) {
        if(data[i].parentId == childId) {
            return findLeaf(data, i, curIndex);
        }
    }
    return [curIndex, parIndex];
}

// check if array contains child 
// and returns child index and parent index
function getChildIndex(data) {
    for(let i = 0; i < data.length; i++) {
        if(data[i].parentId != null) {
            for(let j = 0; j < data.length; j++) {
                if(data[j].dataId == data[i].parentId) 
                    return [i, j];
            }
        }
    }
    return [-1];
}

function normalize(data) {
    // get child and start from it
    let childIndex = getChildIndex(data);
    while(childIndex[0] !== -1) {
        // check if dataId and parentId are same
        // if it's same, set parentId to null
        // to remove infinite recursive call
        if(childIndex[0] == childIndex[1]) {
            data[childIndex[0]].parentId = null;
            childIndex = getChildIndex(data);
            continue;
        }
        // get leaf index and its parent index
        const [cIndex, pIndex] = findLeaf(data, childIndex[0], childIndex[1]);
        // correcting data structure before inserting child to parent
        if(data[pIndex].children == undefined)
            data[pIndex].children = [];
        delete data[cIndex].parentId;
        delete data[cIndex].dataId;
        if(data[cIndex].children != undefined) {
            cchildren = data[cIndex].children;
            delete data[cIndex].children;
            data[cIndex] = { data: data[cIndex], children: cchildren };
        }
        // insert children to parent
        data[pIndex].children.push({ data: data[cIndex] });
        // reconfiguring data by removing inserted child
        data = [...data.slice(0, cIndex), ...data.slice(cIndex+1)];
        // check if there is child left, to loop again
        childIndex = getChildIndex(data);
    }
    // there is no child, it's time to normalize parent structure.
    for(let i = 0; i < data.length; i++) {
        delete data[i].dataId;
        delete data[i].parentId;
        //const children = data[i].children;
        //delete data[i].children;
        //data[i] = children ? { data: data[i], children: children } : { data: data[i] }
    }

    return data;
}

console.log(normalize(data));

【讨论】:

  • 这是非常接近的唯一一件事,我得到了一个额外的数据密钥。顶部标签数据不应该存在 "data": { "data": { "name": "some name", "description": null }, "children": [{ "data": { "name": some name , "description": null, } }, { "data": { "name": some name, "description": "null", } }] }
  • 额外的数据密钥?您的意思是结果中存在您不需要的内容或结果中缺少某些数据?
  • 我希望数据格式像primeng "primefaces.org/primeng/#/treetable"
  • 看起来您想要的与您在问题中提到的目标结构不同。请相应地编辑您的问题
猜你喜欢
  • 1970-01-01
  • 2017-07-25
  • 2021-08-21
  • 2019-03-07
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 2023-03-18
  • 1970-01-01
相关资源
最近更新 更多