Получить всех родителей во вложенном объекте, используя рекурсию - PullRequest
4 голосов
/ 29 марта 2020

У меня есть следующий объект

const object = {
    id: "1",
    name: "a",
    children: [
        {
            id: "2",
            name: "b",
            children: [
                {
                    id: "3",
                    name: "c"
                }
            ]
        },
        {
            id: "4",
            name: "d"
        }
    ]
};

Мне нужна функция, которая принимает объект и идентификатор последнего потомка и возвращает путь, например, следующий вызов: getPath(object, '3'); должен вернуть [{id: 1}, {id: 2}, {id: 3}] .

Я создал функцию, но могу получить доступ только к первому родителю.

function getPath(model, id, parent) {
    if (model == null) {
        return;
    }
    if (model.id === id) {
        console.log(model.id, parent.id)
    }
    if (model.children) {
        model.children.forEach(child => getPath(child, id, model));
    }
}

PS: объект имеет неизвестную глубину.

Ответы [ 3 ]

3 голосов
/ 29 марта 2020

Это довольно близко. Подумайте о передаче всего массива path в вашу рекурсивную функцию. Ниже приведена слегка измененная версия того, что у вас есть для достижения этой цели.

function getPath(model, id, path) {
    if (!path) {
      path = [];
    }

    if (model == null) {
        return;
    }
    if (model.id === id) {
        console.log(model.id, path)
    }
    if (model.children) {
        model.children.forEach(child => getPath(child, id, [...path, model.id]));
    }
}

const object = {
    id: "1",
    name: "a",
    children: [
        {
            id: "2",
            name: "b",
            children: [
                {
                    id: "3",
                    name: "c"
                }
            ]
        },
        {
            id: "4",
            name: "d"
        }
    ]
};

getPath(object, "3");
1 голос
/ 29 марта 2020

const object = {
  id: "1",
  name: "a",
  children: [
    {
      id: "2",
      name: "b",
      children: [
        {
          id: "3",
          name: "c"
        },
        {
          id: "5",
          name: "c"
        }
      ]
    },
    {
      id: "4",
      name: "d"
    }
  ]
};

const getPath = (obj, id, paths = []) => {
  if (obj.id == id) return [{ id: obj.id }];
  if (obj.children && obj.children.length) {
    paths.push({ id: obj.id });
    let found = false;
    obj.children.forEach(child => {
      const temPaths = getPath(child, id);
      if (temPaths) {
        paths = paths.concat(temPaths);
        found = true;
      }
    });
    !found && paths.pop();
    return paths;
  }
  return null;
};
console.log(getPath(object, "5"));
console.log(getPath(object, "2"));
console.log(getPath(object, "3"));
console.log(getPath(object, "4"));
.as-console-row {color: blue!important}
1 голос
/ 29 марта 2020

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

function getPath(model, id) {
    var path,
        item = { id: model.id };

    if (!model || typeof model !== 'object') return;

    if (model.id === id) return [item];    
    
    (model.children || []).some(child => path = getPath(child, id));
    return path && [item, ...path];
    
}
const object = { id: "1", name: "a", children: [{ id: "2", name: "b", children: [{ id: "3", name: "c" }] }, { id: "4", name: "d" }] };

console.log(getPath(object, '42')); // undefined
console.log(getPath(object, '3'));  // [{ id: 1 }, { id: 2 }, { id: 3 }]
.as-console-wrapper { max-height: 100% !important; top: 0; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...