简体   繁体   English

PHP:使用递归函数从多数组中搜索并返回值

[英]PHP: Search and return value from multi-array with Recursive Function

I have a multi-dimensional array of objects (see sample data below). 我有一个多维的对象数组(参见下面的示例数据)。 Now I want to search a value (or property) in the data. 现在我想搜索数据中的值(或属性)。 If the value is found, the function should return the right object and stop searching. 如果找到该值,则该函数应返回正确的对象并停止搜索。

I found three solutions to do this with a recursive function. 我找到了三个使用递归函数执行此操作的解决方案。 But nothing works like described above. 但没有任何作用如上所述。

The first is my own solution: 首先是我自己的解决方案:

public static function getPathForUrl($folderContentDetails, string $url, $result = NULL)
{
    foreach($folderContentDetails as $key => $item)
    {
        if($item->url === $url)
        {
            $result = $item;
        }
        elseif($item->elementType === "folder")
        {
            $result = self::getPathForUrl($item->folderContent, $url, $result);
        }
    }
    return $result;
}

If you call the function like this: 如果你这样调用函数:

print_r(self::getPathForUrl($data, 'order/abc/alpha');

then it returns the right object. 然后它返回正确的对象。 The downside is, that the function searches the whole data and finally returns the result. 缺点是,该函数搜索整个数据并最终返回结果。 I did not find a way to stop the function, if a result is found, so its wasting resources. 如果找到结果,我没有找到停止该功能的方法,因此浪费了资源。

The second (standard-)solution that you will find in the web, looks like this: 您将在Web中找到的第二个(标准)解决方案如下所示:

public static function getPathForUrl($folderContentDetails, string $url)
{
    foreach($folderContentDetails as $key => $item)    
    {
        if($url === $item->url OR ($item->elementType == "folder" && Folder::getPathForUrl($item->folderContent, $url) !== false)) 
        {
            print_r('inner: <br/>'.$item->url);
            // prints more then one value, depending on your data, in my case :
            // /order/abc/alpha
            // /order/abc
            // /order
            return $item;
        }
    }
    return false;
}

This function stops, if it finds the right value. 如果找到正确的值,此函数将停止。 But for some reason it returns more than one object, and the final object is wrong (see code-comments). 但由于某种原因,它返回多个对象,并且最终对象是错误的(参见代码注释)。

The last solution looks like this: 最后的解决方案如下所示:

public static function getPathForUrl($folderContentDetails, string $url)
{           
    foreach($folderContentDetails as $key => $item)
    {
        if($item->elementType == "folder" && $item->url != $url)
        {
            return self::getPathForUrl($item->folderContent, $url); 
            // iterates only the first sub-folder, then stops
        }
        elseif($item->url == $url)
        {
            print_r($item); //nothing, if not found in first sub-folder
            return $item; // nothing, if not found in first sub-folder
        }
    }
    return false;
}

If you return the result of the recursive function, then the function goes down to the first nested element and stops there, so it does not go up again to search the other elements. 如果返回递归函数的结果,则函数将向下移动到第一个嵌套元素并停在那里,因此它不会再次上升以搜索其他元素。

If you do not return the result, the function searches the whole data but, of course, does not return the right object. 如果不返回结果,该函数将搜索整个数据,但当然不会返回正确的对象。

I probably do not understand the concept of recursion properly. 我可能不正确理解递归的概念。 Any help is highly welcome. 任何帮助都非常欢迎。

These are some sample data: 这些是一些示例数据:

Array
(
[0] => stdClass Object
    (
        [elementType] => folder
        [path] => 
        [url] => /getting-started
        [folderContent] => Array
            (
                [0] => stdClass Object
                    (
                        [elementType] => file
                        [path] => \0_getting_started\01-installation.md
                        [url] => /getting-started/installation
                    )

                [1] => stdClass Object
                    (
                        [elementType] => file
                        [path] => \0_getting_started\02-system-settings.md
                        [url] => /getting-started/system-settings
                    )

                [2] => stdClass Object
                    (
                        [elementType] => file
                        [path] => \0_getting_started\index.md
                        [url] => /getting-started/index
                    )

            )

    )

[1] => stdClass Object
    (
        [elementType] => folder
        [path] => 
        [url] => /order
        [folderContent] => Array
            (
                [0] => stdClass Object
                    (
                        [elementType] => folder
                        [path] => \2_order
                        [url] => /order/abc
                        [folderContent] => Array
                            (
                                [0] => stdClass Object
                                    (
                                        [elementType] => file
                                        [path] => \2_order\abc\alpha.md
                                        [url] => /order/abc/alpha
                                    )
                            )

                    )
            )

    )

[3] => stdClass Object
    (
        [elementType] => file
        [path] => \index.md
        [url] => /index
   )
)

Return exits the function so if you want the first result just return it in your condition 返回退出函数,所以如果你想要第一个结果只是在你的条件下返回它

public static function getPathForUrl($folderContentDetails, string $url, $result = NULL)
{
    foreach($folderContentDetails as $key => $item)
    {
        if($item->url === $url)
        {
            return $item;
        }
        elseif($item->elementType === "folder")
        {
            $result = self::getPathForUrl($item->folderContent, $url, $result);
        }
    }
    return $result;
}

If you want to stop after a match of value is made; 如果你想在价值匹配后停止; just return inside the condition; 只是回到条件内;

public static function getPathForUrl($folderContentDetails, string $url, $result = NULL)
{
    foreach($folderContentDetails as $key => $item)
    {
        if($url === $item->url)
        {
            return $item;
        }

        if("folder" === $item->elementType)
        {
          return self::getPathForUrl($item->folderContent, $url, $result);
        }
    }
}

PS: Keeping in mind Best practices for if/return :) PS:记住if / return的最佳实践:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM