我有一个对象数组。数组中的每个对象都有一个id和一个item属性,它是一个包含其他对象的数组。我需要能够通过id在数组中找到一个元素。这是我到目前为止所做的一个示例,但递归函数总是返回undefined。
当我多次递归调用函数时,如何退出函数并返回项目?
$(function () {
var treeDataSource = [{
id: 1,
Name: "Test1",
items: [{
id: 2,
Name: "Test2",
items: [{
id: 3,
Name: "Test3"
}]
}]
}];
var getSubMenuItem = function (subMenuItems, id) {
if (subMenuItems && subMenuItems.length > 0) {
for (var i = 0; i < subMenuItems.length; i++) {
var item;
if (subMenuItems[i].Id == id) {
item = subMenuItems[i];
return item;
};
getSubMenuItem(subMenuItems[i].items, id);
};
};
};
var searchedItem = getSubMenuItem(treeDataSource, 3);
alert(searchedItem.id);
});
答案 0 :(得分:23)
你应该替换
getSubMenuItem(subMenuItems[i].items, id);
与
var found = getSubMenuItem(subMenuItems[i].items, id);
if (found) return found;
以便在找到元素时返回该元素。
请注意属性的名称,javascript区分大小写,因此您还必须替换
if (subMenuItems[i].Id == id) {
与
if (subMenuItems[i].id == id) {
最终(清理)代码:
var getSubMenuItem = function (subMenuItems, id) {
if (subMenuItems) {
for (var i = 0; i < subMenuItems.length; i++) {
if (subMenuItems[i].id == id) {
return subMenuItems[i];
}
var found = getSubMenuItem(subMenuItems[i].items, id);
if (found) return found;
}
}
};
答案 1 :(得分:1)
我知道它来晚了,但这是一种更通用的方法
Array.prototype.findRecursive = function(predicate, childrenPropertyName){
if(!childrenPropertyName){
throw "findRecursive requires parameter `childrenPropertyName`";
}
let array = [];
array = this;
let initialFind = array.find(predicate);
let elementsWithChildren = array.filter(x=>x[childrenPropertyName]);
if(initialFind){
return initialFind;
}else if(elementsWithChildren.length){
let childElements = [];
elementsWithChildren.forEach(x=>{
childElements.push(...x[childrenPropertyName]);
});
return childElements.findRecursive(predicate, childrenPropertyName);
}else{
return undefined;
}
}
使用它:
var array = [<lets say an array of students who has their own students>];
var joe = array.findRecursive(x=>x.Name=="Joe", "students");
如果要过滤而不是查找
Array.prototype.filterRecursive = function(predicate, childProperty){
let filterResults = [];
let filterAndPushResults = (arrayToFilter)=>{
let elementsWithChildren = arrayToFilter.filter(x=>x[childProperty]);
let filtered = arrayToFilter.filter(predicate);
filterResults.push(...filtered);
if(elementsWithChildren.length){
let childElements = [];
elementsWithChildren.forEach(x=>{
childElements.push(...x[childProperty]);
});
filterAndPushResults(childElements);
}
};
filterAndPushResults(this);
return filterResults;
}
答案 2 :(得分:0)
是的,谢谢,但是我有一个问题,如果有像您这样的嵌套数组想要自己构建一个菜单面板,并且不管它在哪里都想获得具有特定ID的项目
示例:
var treeDataSource = [ { Id: 1, Name: "s", Children: [ { Id: 2, Name: "m", Children: [ { Id: 3, Name: "q", Children: [ { Id: 4, Name: "a", Children: [ { Id: 5, Name: "w", Children: [ { Id: 6, Name: "needed", Children: [], } ], } ], } ], } ], } ], }, ]
我想退回符合ID 6的商品