#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. Нет. Я хочу, чтобы дочерний элемент и дочерний элемент (вложенный) из родительского узла выполняли поиск.