Необходимо преобразовать массив объектов, которые имеют родительские и дочерние отношения, и преобразовать их в узлы таблицы первичного дерева - PullRequest
0 голосов
/ 12 октября 2018

Указан список сглаженного массива объектов, среди которых есть родительские дочерние отношенияМне нужно преобразовать в простую структуру данных таблицы дерева.Я хотел бы расширить всех детей за один раз.

Моя конечная цель будет иметь следующую структуру:

[{
        "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
}

]

Ответы [ 3 ]

0 голосов
/ 12 октября 2018

Вот возможное решение, которое "злоупотребляет" 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);

Конечно, вы можете вносить дополнительные изменения, чтобы извлекать только определенные свойства из ваших объектов данных.

0 голосов
/ 12 октября 2018

Решение с рекурсивной функцией

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));
0 голосов
/ 12 октября 2018

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));
...