javascript 递归查找数组中的元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14559286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 21:58:42  来源:igfitidea点击:

Find an element in an array recursively

javascriptalgorithm

提问by Mdb

I have an array of objects. Every object in the array has an id and an item property that is an array containing other object. I need to be able to find an element in an array by id. Here is a sample of what I have done so far, but the recursive function is always returning undefined.

我有一个对象数组。数组中的每个对象都有一个 id 和一个 item 属性,该属性是一个包含其他对象的数组。我需要能够通过 id 在数组中找到一个元素。这是我到目前为止所做的示例,但递归函数始终返回未定义。

How can I quit the function and return the item when I have called the function recursively several times?

当我多次递归调用该函数时,如何退出该函数并返回该项目?

   $(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

js小提琴

回答by Denys Séguret

You should replace

你应该更换

  getSubMenuItem(subMenuItems[i].items, id);

with

  var found = getSubMenuItem(subMenuItems[i].items, id);
  if (found) return found;

in order to return the element when it is found.

为了在找到元素时返回元素。

And be careful with the name of the properties, javascript is case sensitive, so you must also replace

并注意属性的名称,javascript区分大小写,因此您还必须替换

  if (subMenuItems[i].Id == id) {

with

  if (subMenuItems[i].id == id) {

Demonstration

示范



Final (cleaned) code :

最终(清理)代码:

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

回答by anaval

I know its late but here is a more generic approach

我知道为时已晚,但这里有一个更通用的方法

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

to use it:

使用它:

var array = [<lets say an array of students who has their own students>];
var joe = array.findRecursive(x=>x.Name=="Joe", "students");

and if you want filter instead of find

如果你想过滤而不是查找

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