Получение всех дочерних элементов из родительских дочерних данных JSON

#javascript #jquery #json #algorithm #search

#javascript #jquery #json #алгоритм #Поиск

Вопрос:

У меня есть родительско-дочерние данные JSON, и я хочу получить все дочерние элементы (вложенные дочерние элементы) от выбранного родителя.

Например, у меня есть данные JSON :

 [{
  "id": 1,
  "parent": 0,
  "name": "Parent"
}, {
  "id": 2,
  "parent": 1,
  "name": "Child 1"
}, {
  "id": 3,
  "parent": 2,
  "name": "Grand Child 1"
}, {
  "id": 4,
  "parent": 2,
  "name": "Grand Child 2"
}, {
  "id": 5,
  "parent": 1,
  "name": "Child 2"
}]
  

И у меня есть функция findAllChildren(1), где «1» — это «родительский», а затем результат функции должен быть :

 [{
  "id": 2,
  "parent": 1,
  "name": "Child 1"
}, {
  "id": 3,
  "parent": 2,
  "name": "Grand Child 1"
}, {
  "id": 4,
  "parent": 2,
  "name": "Grand Child 2"
}, {
  "id": 5,
  "parent": 1,
  "name": "Child 2"
}]
  

И в другом случае, если я вызову findAllChildren(2), результат функции должен выглядеть следующим образом :

 [{
  "id": 3,
  "parent": 2,
  "name": "Grand Child 1"
}, {
  "id": 4,
  "parent": 2,
  "name": "Grand Child 2"
}]
  

Каков правильный способ создания функции для решения этого случая? Спасибо.

Комментарии:

1. пожалуйста, добавьте желаемый результат. упорядочены ли данные? есть ли у вас больше вложенных уровней, чем указано выше? что должно произойти, если вы хотите получить id = 1 ?

2. уже добавлено

Ответ №1:

Вы можете просто перебирать исходные данные и искать элементы с указанным идентификатором в качестве parent_id. Если найдено, проделайте то же самое рекурсивно с идентификатором элемента.

Проверьте это здесь: https://jsfiddle.net/6ydog1tj/2 /

 function findAllChildren (id, results, depth) {
    for (d in data) {
        if (data[d].parent == id) {
            data[d].depth = depth
            results.push(data[d])
            findAllChildren(data[d].id, results, depth   1)
        }
    }
}

var results = []
findAllChildren(1, results, 0)

$('body').append(results.map(function (element) { return Array(element.depth   1).join(' -> ')   element.name   '<br>' }))

console.log(results)
  

выводит

 Child 1
-> Grand Child 1
-> Grand Child 2
Child 2
  

Комментарии:

1. Привет, Мартин, я хочу, чтобы данные get включали в себя и внука.

2. Не могли бы вы изменить свой вопрос на желаемый результат для заданного ввода? В вопросе, с которым он извлекает элементы parent=2 .

3. Теперь я понял. Изменен ответ и jsfiddle, проверьте это

4. Добро пожаловать. Удачи в вашем проекте. Эй, может быть, вы могли бы также структурировать данные вложенным способом, чтобы сделать это намного проще. Проверьте это здесь: jsfiddle.net/eokf884p/1

5. Спасибо за ваше предложение. Может быть, для другого случая, потому что я извлекаю данные из СУБД.

Ответ №2:

Я предлагаю перебрать все данные и построить древовидный объект со свойствами, чтобы начать поиск со всеми данными id .

Затем объект обходится, и дочерние элементы повторяются для получения результата.

 function getDescendant(id) {
    var result = [];
    Array.isArray(object[id].children) amp;amp; object[id].children.forEach(function iter(a) {
        result.push({ id: a.id, parent: a.parent, name: a.name });
        Array.isArray(a.children) amp;amp; a.children.forEach(iter);
    });
    return resu<
}

var data = [{ id: 1, parent: 0, name: "Parent" }, { id: 2, parent: 1, name: "Child 1" }, { id: 3, parent: 2, name: "Grand Child 1" }, { id: 4, parent: 2, name: "Grand Child 2" }, { id: 5, parent: 1, name: "Child 2" }],
    object = function (data, root) {
        var o = {};
        data.forEach(function (a) {
            a.children = o[a.id] amp;amp; o[a.id].children;
            o[a.id] = a;
            o[a.parent] = o[a.parent] || {};
            o[a.parent].children = o[a.parent].children || [];
            o[a.parent].children.push(a);
        });
        return o;
    }(data, 0);

console.log(getDescendant(1));
console.log(getDescendant(2));
console.log(object);  
 .as-console-wrapper { max-height: 100% !important; top: 0; }  

Комментарии:

1. Привет @nina-scholz, я хочу, чтобы данные включали в себя внука. например: если я передам parent=1, я должен получить данные с id = 2, включая дочерний элемент узла с его дочерним элементом.

2. Спасибо @nina-scholz за вашу помощь, я получаю отличное решение от Мартина.

Ответ №3:

Вы можете использовать Array.prototype.filter для удаления элементов из массива, которые не соответствуют условию предиката.

filter будет перебирать массив и запускать функцию для каждой итерации. если возвращаемое значение равно true, элемент будет находиться в возвращаемом массиве.

Функция, переданная в filter, удалена. parentId он заблокирует родительский идентификатор, который вы ищете в области видимости, и вернет функцию, которую будет запускать filter.

 const data = [{
  "id": 1,
  "parent": 0,
  "name": "Parent"
}, {
  "id": 2,
  "parent": 1,
  "name": "Child 1"
}, {
  "id": 3,
  "parent": 2,
  "name": "Grand Child 1"
}, {
  "id": 4,
  "parent": 2,
  "name": "Grand Child 2"
}, {
  "id": 5,
  "parent": 1,
  "name": "Child 2"
}]

function parentId(id) {
  return function(item) {
    return item.parent === id
  }
}

console.log(
  data.filter(parentId(2))
)  

Комментарии:

1. Привет @synthet1c, я хочу, чтобы данные get включали в себя и внука.

2. @Hidayat вы имеете в виду, что хотите структурировать его в виде дерева?

3. Нет. Я хочу, чтобы дочерний элемент и дочерний элемент (вложенный) из родительского узла выполняли поиск.