Связать ребенка и родителя по основанию c уровня глубины - PullRequest
1 голос
/ 23 апреля 2020

У меня есть все мои родительские дети в одном массиве данных. Я хочу добавить новый атрибут (уровень) для каждого объекта.

Учитывая, что у меня есть данные как

 var data = [
        {
            id: 1,
            parent_id: 0,
            name: "Child1",
        },
        {
            id: 4,
            parent_id: 1,
            name: "Child11",

        },

        {
            id: 5,
            parent_id: 4,
            name: "Child111",
        },
        {
            id: 11,
            parent_id: 4,
            name: "Child112"
        },


        {
            id: 13,
            parent_id: 11,
            name: "Child1121",
        },

        {
            id: 21,
            parent_id: 11,
            name: "Child1122"
        },
        {
            id: 22,
            parent_id: 11,
            name: "Child1123"
        },
        {
            id: 24,
            parent_id: 1,
            name: 'Child12'
        }

    ]

Я хочу child-parent отношение, основанное на parent_id потомков, и назначить новый атрибут в каждом объекте массива как уровень, который представляет уровень глубины потомков на основе его родитель. Мой Ожидаемый результат:

var data = [
            {
                id: 1,
                parent_id: 0, <-------represents root 
                name: "Child1",
                level:0   <--------level based on its parent_id 
            },
            {
                id: 4,
                parent_id: 1
                name: "Child11",
                level:1

            },
            {
                id: 5,
                parent_id: 4,
                name: "Child111",
                level:2
            },
            {
                id: 11,
                parent_id: 4,
                name: "Child112",
                level:2
            },


            {
                id: 13,
                parent_id: 11,
                name: "Child1121",
                level:3
            },

            {
                id: 21,
                parent_id: 11,
                name: "Child1122",
                level:3
            },
            {
                id: 22,
                parent_id: 11,
                name: "Child1123",
                level:3
            },
            {
                id: 24,
                parent_id: 1,
                name: 'Child12',
                level:1
            }

        ]


Мой код


 function buildTree(elements, parent_id, level = 0) {

                elements.forEach(element => {


                    if (element['parent_id'] == parent_id) {
                        console.log('parent_id', parent_id);
                        // elements.filter(item=>item!==element);
                        element['level'] = level;

                    }
                    else{
                        buildTree(elements,parent_id,level+1);
                    }





                })




            return elements;




        }



Ответы [ 3 ]

3 голосов
/ 23 апреля 2020

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

var data = [{ id: 1, parent_id: 0, name: "Child1" }, { id: 4, parent_id: 1, name: "Child11" }, { id: 5, parent_id: 4, name: "Child111" }, { id: 11, parent_id: 4, name: "Child112" }, { id: 13, parent_id: 11, name: "Child1121" }, { id: 21, parent_id: 11, name: "Child1122" }, { id: 22, parent_id: 11, name: "Child1123" }, { id: 24, parent_id: 1, name: 'Child12' }],
    levels = {},
    result = data.map(o => ({
        ...o,
        level: levels[o.id] = o.parent_id in levels
            ? levels[o.parent_id] + 1
            : 0
    }));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 23 апреля 2020

Если данные не отсортированы таким образом, чтобы родительский элемент гарантированно находился раньше, чем любой из его дочерних элементов, тогда используйте Map с ключами id, что также повышает эффективность (нет линейного поиска в каждой итерации) :

let data = [{ id: 1, parent_id: 0, name: "Child1" }, { id: 4, parent_id: 1, name: "Child11" }, { id: 5, parent_id: 4, name: "Child111" }, { id: 11, parent_id: 4, name: "Child112" }, { id: 13, parent_id: 11, name: "Child1121" }, { id: 21, parent_id: 11, name: "Child1122" }, { id: 22, parent_id: 11, name: "Child1123" }, { id: 24, parent_id: 1, name: 'Child12' }];

// optional step if you don't want to mutate the original objects in the array:
data = data.map(o => ({...o}));

const map = new Map(data.map(o => [o.id, o])).set(0, { level: -1 });
const setLevel = o => "level" in o ? o.level : (o.level = 1 + setLevel(map.get(o.parent_id)));
data.forEach(setLevel);

console.log(data);

Вы можете опустить необязательное назначение, когда все в порядке, добавив свойство level к существующим объектам. Но если вы хотите, чтобы исходные объекты данных оставались нетронутыми, и у вас были вновь созданные объекты для хранения свойства level, сохраните эту строку в.

1 голос
/ 23 апреля 2020

Попробуйте это

let parentLevel = []

data.map(parent => {
    const { parent_id } = parent
    if (!parentLevel.includes(parent_id)) {
        parentLevel.push(parent_id);
    }
})

const updatedData = data.map(parent => {
    const { parent_id } = parent

    parent.level = parentLevel.indexOf(parent_id)

    return parent
})

console.log(updatedData);

Результат

(8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {id: 1, parent_id: 0, name: "Child1", level: 0}
1: {id: 4, parent_id: 1, name: "Child11", level: 1}
2: {id: 5, parent_id: 4, name: "Child111", level: 2}
3: {id: 11, parent_id: 4, name: "Child112", level: 2}
4: {id: 13, parent_id: 11, name: "Child1121", level: 3}
5: {id: 21, parent_id: 11, name: "Child1122", level: 3}
6: {id: 22, parent_id: 11, name: "Child1123", level: 3}
7: {id: 24, parent_id: 1, name: "Child12", level: 1}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...