У меня есть действующий JSON. Он описывает структуру дерева:
{
"items": [
{
"id": "d1"
},
{
"id": "2",
"children": [
{
"id": "3"
},
{
"id": "4"
},
{
"id": "5",
"children": [
{
"id": "6"
},
{
"id": "7",
"children": [
{
"id": "8"
},
{
"id": "9"
}
]
},
{
"id": "10"
}
]
},
{
"id": "11"
},
{
"id": "12"
}
]
},
{
"id": "13"
},
{
"id": "14"
}
]
}
Мне нужно получить любой из "элементов" по id и любому из дочерних элементов. Например. Первоначально я пробовал grep:
var returnedData = $.grep(obj.items, function(element, index){return element.id == "2";
});
Это отлично работает для элемента с id == 2, но полностью не удается, когда я пытаюсь получить element.id == "7"
Любая помощь будет оценена. Заранее спасибо.
Вы можете сделать рекурсивную функцию для поиска в данных:
function find(source, id)
{
for (key in source)
{
var item = source[key];
if (item.id == id)
return item;
// Item not returned yet. Search its children by recursive call.
if (item.children)
{
var subresult = find(item.children, id);
// If the item was found in the subchildren, return it.
if (subresult)
return subresult;
}
}
// Nothing found yet? return null.
return null;
}
// In the root object, the array of items is called 'items', so we pass in
// data.items to look into. The root object itself doesn't seem to have an id anyway.
var result = find(data.items, 7);
// Show the name of item 7, if it had one...
alert(result.name);
Демо: http://jsfiddle.net/rj26H/
В этой функции я просто зациклился на объекте, поэтому он немного более подробный. Возможно, вы также можете использовать $.grep для выполнения поиска и сделать код немного меньше. Во всяком случае, трюк заключается в поиске всех детей, если элемент не найден на основном уровне. По-видимому, grep
не работает рекурсивным образом.
Попробуй это:
var id = 7;
var data = {"items": [{"id": "d1"},{"id": "2","children": [{"id": "3"},{"id": "7"},{"id": "11"},{"id": "12"}]}]};
function search(values) {
$.each(values, function(i, v) {
if (v.id == id) {
console.log('found', v);
return false;
}
if (v.children) {
search(v.children);
}
});
}
search(data.items);
foo
или bar
подходящими именами.
Я знаю, что это уже ответили, но я хотел показать, как вы могли бы использовать новые функции JavaScript 1.7 для решения этой проблемы. Обратите внимание, что такой же подход можно было бы использовать без поддержки генераторов, но код был бы длиннее.
//Returns an iterator that knows how to walk a tree
function treeIterator(root, childGetter, childCountGetter) {
let stack = [root], node;
while (node = stack.pop()) {
yield node;
for (let i = childCountGetter(node); i--;) stack.push(childGetter(node, i));
}
}
//Our custom search function
function findNodeById(tree, id) {
let it = treeIterator(tree,
function (node, i) { return node.children[i]; },
function (node) { return node.children? node.children.length : 0; }
);
for (let node in it) if (node.id === id) return node;
return null;
}
var tree = {
id: 'root',
children: [
{ id: 'a' },
{
id: 'b',
children: [
{ id: 'b1' },
{ id: 'b2' }
]
},
{ id: 'c' }
]
};
findNodeById(tree, 'b1'); //Object { id="b1"}
Обратите внимание, что вы также можете установить __iterator__
в структуре данных, чтобы функции, которые необходимо перебирать по этой структуре данных, не должны были знать детали реализации.
tree.__iterator__ = treeIterator.bind(null, tree,
function (node, i) { return node.children[i]; },
function (node) { return node.children? node.children.length : 0; }
);
Тогда функция findNodeById
может быть:
function findNodeById(tree, id) {
for (let node in it) if (node.id === id) return node;
return null;
}