递归查找数组中的元素

17
我有一个对象数组。数组中的每个对象都有一个id和一个包含其他对象的item属性数组。我需要能够通过id在数组中找到一个元素。这是我已经做的一些示例,但递归函数总是返回undefined。
当我多次递归调用该函数时,如何退出函数并返回item?
   $(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);
});

jsFiddle

2个回答

38

你应该替换

  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;
        }
    }
};

谢谢,但我有一个问题,如果有一个嵌套数组,比如你想自己构建菜单面板,并想获取具有特定ID的项目,无论它在哪里。例如:` - Un1xCr3w

3
我知道现在有点晚了,但这里有一个更通用的方法。
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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接