使用RecursiveArrayIterator获取所有父节点 [英] Get all parent nodes with RecursiveArrayIterator

查看:114
本文介绍了使用RecursiveArrayIterator获取所有父节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我想使用

$foo = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack));

方法,但不保留返回foreach()的平面数组,而是保留结构,但仅返回单个重孙子节点及其父节点.这在PHP中可行吗?


我的任务是优化公司的某些(可怕的)代码库.我发现了一个通过数组递归查找键的函数.我不能用简单的array_search()array_key_exists()替换它,因为自定义函数还返回匹配的(找到的)键的父节点,而不仅仅是true.

如何使用RecursiveArrayIteratorRecursiveIteratorIterator或其他的内置函数(即,尽可能少的自定义代码)从搜索数组中返回与其父树匹配的节点?我想获得尽可能最快的功能,因为该功能目前花8秒执行14000次,因此我需要使用内置功能.<​​/p>

我下面的现有尝试非常慢.

function search_in_array($needle, $haystack) {
    $path = array();

    $it = new RecursiveArrayIterator($haystack);
    iterator_apply($it, 'traverse', array($it, $needle, &$path));

    return $path;
}

function traverse($it, $needle, &$path) {
    while($it->valid()) {
        $key = $it->key();
        $value = $it->current();

        if(strcasecmp($value['id'], $needle) === 0) {
            $path[] = $key;
            return;
        } else if($it->hasChildren()) {
            $sub = null;
            traverse($it->getChildren(), $needle, &$sub);
            if($sub) {
                $path[$key] = $sub;
            }
        }

        $it->next();
    }
}

$needle = TVALL的示例输出如下所示:

Array (
    [HOMECINEMA] => Array (
        [children] => Array (
            [HC-VISION] => Array (
                [children] => Array (
                    [0] => TVALL
                )
            )
        )
    )
)

搜索数组看起来像这样(很抱歉).有两个以上的顶级节点,但是为了简洁起见,我将其删节了:

Array(2) (
    [HOMECINEMA] => Array (
        [id] => HOMECINEMA
        [position] => 2
        [title] => TV & Home Cinema
        [children] => Array (
            [HC-VISION] => Array (
                [id] => HC-VISION
                [title] => LCD & Plasma
                [children] => Array (
                    [TVALL] => Array (
                        [id] => TVALL
                        [title] => All TVs
                    )
                    [LCD2] => Array (
                        [id] => LCD2
                        [title] => LCD/LED TVs
                    )
                    [PLASMA] => Array (
                        [id] => PLASMA
                        [title] => Plasma TVs
                    )
                    [3DTV] => Array (
                        [id] => 3DTV
                        [title] => 3D TV
                    )
                    [LED] => Array (
                        [id] => LED
                        [title] => SMART TVs
                    )
                    [PROJECTORS] => Array (
                        [id] => PROJECTORS
                        [title] => Projectors
                    )
                    [SYS-HOMECINEMATV] => Array (
                        [id] => SYS-HOMECINEMATV
                        [title] => TV Home Cinema Systems
                    )
                )
            )
            [HC-SEPARATES] => Array (
                [id] => HC-SEPARATES
                [title] => Home Cinema Separates
                [children] => Array (
                    [DVDRECORDERS] => Array (
                        [id] => DVDRECORDERS
                        [title] => DVD Recorders
                    )
                    [HDDVD] => Array (
                        [id] => HDDVD
                        [title] => Blu-ray
                    )
                    [AVRECEIVERS] => Array (
                        [id] => AVRECEIVERS
                        [title] => AV Receivers
                    )
                    [DVDPLAYERS] => Array (
                        [id] => DVDPLAYERS
                        [title] => DVD Players
                    )
                    [FREEVIEW] => Array (
                        [id] => FREEVIEW
                        [title] => Digital Set Top Boxes
                    )
                    [DVDPACKAGESYSTEMS-3] => Array (
                        [id] => DVDPACKAGESYSTEMS-3
                        [title] => 1 Box Home Cinema Systems
                    )
                    [HOMECINEMADEALS] => Array (
                        [id] => HOMECINEMADEALS
                        [title] => Home Cinema System Deals
                    )
                )
            )
            [SPEAKER2] => Array (
                [id] => SPEAKER2
                [title] => Speakers
                [children] => Array (
                    [SPEAKERPACKAGES] => Array (
                        [id] => SPEAKERPACKAGES
                        [title] => Speaker packages
                    )
                    [SOUNDBARS] => Array (
                        [id] => SOUNDBARS
                        [title] => Soundbars
                    )
                    [CENTRES] => Array (
                        [id] => CENTRES
                        [title] => Centres
                    )
                    [SUBWOOFERS] => Array (
                        [id] => SUBWOOFERS
                        [title] => Subwoofers
                    )
                    [FLOORSTANDING] => Array (
                        [id] => FLOORSTANDING
                        [title] => Floorstanders
                    )
                    [INSTALLATIONSPEAKERS] => Array (
                        [id] => INSTALLATIONSPEAKERS
                        [title] => Installation Speakers
                    )
                    [STAND-MOUNT] => Array (
                        [id] => STAND-MOUNT
                        [title] => Bookshelf Speakers
                    )
                )
            )
            [HC-ACCYS] => Array (
                [id] => HC-ACCYS
                [title] => Accessories
                [children] => Array (
                    [AVESSENTIALS] => Array (
                        [id] => AVESSENTIALS
                        [title] => AV Interconnects
                    )
                    [PLASMALCDSTANDSBRACKETS1] => Array (
                        [id] => PLASMALCDSTANDSBRACKETS1
                        [title] => TV Accessories
                    )
                    [RACKS] => Array (
                        [id] => RACKS
                        [title] => TV Racks
                    )
                    [HIFIRACKS] => Array (
                        [id] => HIFIRACKS
                        [title] => HiFi Racks
                    )
                    [PROJECTORACCYS] => Array (
                        [id] => PROJECTORACCYS
                        [title] => Projector Screens/Accessories
                    )
                )
            )
        )
    )
    [SPEAKERS] => Array (
        [id] => SPEAKERS
        [position] => 3
        [title] => Speakers
        [children] => Array (
            [SPK-HIFI] => Array (
                [id] => SPK-HIFI
                [title] => Hi-Fi
                [children] => Array (
                    [STAND-MOUNT] => Array (
                        [id] => STAND-MOUNT
                        [title] => Bookshelf Speakers
                    )
                    [FLOORSTANDING] => Array (
                        [id] => FLOORSTANDING
                        [title] => Floorstanders
                    )
                    [INSTALLATIONSPEAKERS] => Array (
                        [id] => INSTALLATIONSPEAKERS
                        [title] => Installation Speakers
                    )
                )
            )
            [SPK-HOMECINEMA] => Array (
                [id] => SPK-HOMECINEMA
                [title] => Home Cinema
                [children] => Array (
                    [SPEAKERPACKAGES] => Array (
                        [id] => SPEAKERPACKAGES
                        [title] => Speaker Packages
                    )
                    [SOUNDBARS] => Array (
                        [id] => SOUNDBARS
                        [title] => Soundbars
                    )
                    [CENTRES] => Array (
                        [id] => CENTRES
                        [title] => Centres
                    )
                    [SUBWOOFERS] => Array (
                        [id] => SUBWOOFERS
                        [title] => Subwoofers
                    )
                )
            )
            [SPK-ACCYS] => Array (
                [id] => SPK-ACCYS
                [title] => Accessories
                [children] => Array (
                    [SPEAKERESSENTIALS1] => Array (
                        [id] => SPEAKERESSENTIALS
                        [title] => Speaker Cables
                    )
                    [SPEAKERSTANDS] => Array (
                        [id] => SPEAKERSTANDS
                        [title] => Speaker Stands
                    )
                    [SPEAKERBRACKETS] => Array (
                        [id] => SPEAKERBRACKETS
                        [title] => Speaker Wall Brackets
                    )
                )
            )
        )
    )
)

解决方案

下面的示例不一定会提高性能(在时间或内存要求上),但是避免了手动递归遍历该结构,并显示了一种更简单的(IMHO)构建方法您所需的输出数组.

function search_in_array($needle, $haystack) {
    $path = array();

    $it = new RecursiveIteratorIterator(
        new ParentIterator(new RecursiveArrayIterator($haystack)),
        RecursiveIteratorIterator::SELF_FIRST
    );

    foreach ($it as $key => $value) {
        if (array_key_exists('id', $value) && strcasecmp($value['id'], $needle) === 0) {
            $path = array($needle);
            for ($i = $it->getDepth() - 1; $i >= 0; $i--) {
                $path = array($it->getSubIterator($i)->key() => $path);
            }
            break;
        }
    }

    return $path;
}

参考

奖金

您还可以使用 RecursiveIteratorIterator :: setMaxDepth()方法将递归限制为n级别更深,如果您的数组也更深.

Essentially, I want to use the

$foo = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack));

Methodology, but instead of returning a flat array for foreach()ing through, keep the structure but only return a single great-grand-child node and it's parent nodes. Is this possible in PHP?


I've been tasked with optimising some of my company's (horrific) codebase. I found a function that recurses through an array, searching for a key. I can't replace this with a simple array_search() or array_key_exists() because the custom function also returns the parent nodes of the matched (found) key, instead of just a true or false.

How can I use RecursiveArrayIterator, RecursiveIteratorIterator or failing that, other built-in functions (i.e. as little custom code as possible) to return a matching node with it's parent tree from a search array? I want to get the fastest function possible, as currently this function spends 8 seconds executing 14 thousand times, hence my requirement to use built-in functions.

My existing attempt (below) is incredibly slow.

function search_in_array($needle, $haystack) {
    $path = array();

    $it = new RecursiveArrayIterator($haystack);
    iterator_apply($it, 'traverse', array($it, $needle, &$path));

    return $path;
}

function traverse($it, $needle, &$path) {
    while($it->valid()) {
        $key = $it->key();
        $value = $it->current();

        if(strcasecmp($value['id'], $needle) === 0) {
            $path[] = $key;
            return;
        } else if($it->hasChildren()) {
            $sub = null;
            traverse($it->getChildren(), $needle, &$sub);
            if($sub) {
                $path[$key] = $sub;
            }
        }

        $it->next();
    }
}

Example output for $needle = TVALL would look like this:

Array (
    [HOMECINEMA] => Array (
        [children] => Array (
            [HC-VISION] => Array (
                [children] => Array (
                    [0] => TVALL
                )
            )
        )
    )
)

The search array looks something like this (sorry for the vast-ness). There are more than two top-level nodes, but I've truncated it for brevity:

Array(2) (
    [HOMECINEMA] => Array (
        [id] => HOMECINEMA
        [position] => 2
        [title] => TV & Home Cinema
        [children] => Array (
            [HC-VISION] => Array (
                [id] => HC-VISION
                [title] => LCD & Plasma
                [children] => Array (
                    [TVALL] => Array (
                        [id] => TVALL
                        [title] => All TVs
                    )
                    [LCD2] => Array (
                        [id] => LCD2
                        [title] => LCD/LED TVs
                    )
                    [PLASMA] => Array (
                        [id] => PLASMA
                        [title] => Plasma TVs
                    )
                    [3DTV] => Array (
                        [id] => 3DTV
                        [title] => 3D TV
                    )
                    [LED] => Array (
                        [id] => LED
                        [title] => SMART TVs
                    )
                    [PROJECTORS] => Array (
                        [id] => PROJECTORS
                        [title] => Projectors
                    )
                    [SYS-HOMECINEMATV] => Array (
                        [id] => SYS-HOMECINEMATV
                        [title] => TV Home Cinema Systems
                    )
                )
            )
            [HC-SEPARATES] => Array (
                [id] => HC-SEPARATES
                [title] => Home Cinema Separates
                [children] => Array (
                    [DVDRECORDERS] => Array (
                        [id] => DVDRECORDERS
                        [title] => DVD Recorders
                    )
                    [HDDVD] => Array (
                        [id] => HDDVD
                        [title] => Blu-ray
                    )
                    [AVRECEIVERS] => Array (
                        [id] => AVRECEIVERS
                        [title] => AV Receivers
                    )
                    [DVDPLAYERS] => Array (
                        [id] => DVDPLAYERS
                        [title] => DVD Players
                    )
                    [FREEVIEW] => Array (
                        [id] => FREEVIEW
                        [title] => Digital Set Top Boxes
                    )
                    [DVDPACKAGESYSTEMS-3] => Array (
                        [id] => DVDPACKAGESYSTEMS-3
                        [title] => 1 Box Home Cinema Systems
                    )
                    [HOMECINEMADEALS] => Array (
                        [id] => HOMECINEMADEALS
                        [title] => Home Cinema System Deals
                    )
                )
            )
            [SPEAKER2] => Array (
                [id] => SPEAKER2
                [title] => Speakers
                [children] => Array (
                    [SPEAKERPACKAGES] => Array (
                        [id] => SPEAKERPACKAGES
                        [title] => Speaker packages
                    )
                    [SOUNDBARS] => Array (
                        [id] => SOUNDBARS
                        [title] => Soundbars
                    )
                    [CENTRES] => Array (
                        [id] => CENTRES
                        [title] => Centres
                    )
                    [SUBWOOFERS] => Array (
                        [id] => SUBWOOFERS
                        [title] => Subwoofers
                    )
                    [FLOORSTANDING] => Array (
                        [id] => FLOORSTANDING
                        [title] => Floorstanders
                    )
                    [INSTALLATIONSPEAKERS] => Array (
                        [id] => INSTALLATIONSPEAKERS
                        [title] => Installation Speakers
                    )
                    [STAND-MOUNT] => Array (
                        [id] => STAND-MOUNT
                        [title] => Bookshelf Speakers
                    )
                )
            )
            [HC-ACCYS] => Array (
                [id] => HC-ACCYS
                [title] => Accessories
                [children] => Array (
                    [AVESSENTIALS] => Array (
                        [id] => AVESSENTIALS
                        [title] => AV Interconnects
                    )
                    [PLASMALCDSTANDSBRACKETS1] => Array (
                        [id] => PLASMALCDSTANDSBRACKETS1
                        [title] => TV Accessories
                    )
                    [RACKS] => Array (
                        [id] => RACKS
                        [title] => TV Racks
                    )
                    [HIFIRACKS] => Array (
                        [id] => HIFIRACKS
                        [title] => HiFi Racks
                    )
                    [PROJECTORACCYS] => Array (
                        [id] => PROJECTORACCYS
                        [title] => Projector Screens/Accessories
                    )
                )
            )
        )
    )
    [SPEAKERS] => Array (
        [id] => SPEAKERS
        [position] => 3
        [title] => Speakers
        [children] => Array (
            [SPK-HIFI] => Array (
                [id] => SPK-HIFI
                [title] => Hi-Fi
                [children] => Array (
                    [STAND-MOUNT] => Array (
                        [id] => STAND-MOUNT
                        [title] => Bookshelf Speakers
                    )
                    [FLOORSTANDING] => Array (
                        [id] => FLOORSTANDING
                        [title] => Floorstanders
                    )
                    [INSTALLATIONSPEAKERS] => Array (
                        [id] => INSTALLATIONSPEAKERS
                        [title] => Installation Speakers
                    )
                )
            )
            [SPK-HOMECINEMA] => Array (
                [id] => SPK-HOMECINEMA
                [title] => Home Cinema
                [children] => Array (
                    [SPEAKERPACKAGES] => Array (
                        [id] => SPEAKERPACKAGES
                        [title] => Speaker Packages
                    )
                    [SOUNDBARS] => Array (
                        [id] => SOUNDBARS
                        [title] => Soundbars
                    )
                    [CENTRES] => Array (
                        [id] => CENTRES
                        [title] => Centres
                    )
                    [SUBWOOFERS] => Array (
                        [id] => SUBWOOFERS
                        [title] => Subwoofers
                    )
                )
            )
            [SPK-ACCYS] => Array (
                [id] => SPK-ACCYS
                [title] => Accessories
                [children] => Array (
                    [SPEAKERESSENTIALS1] => Array (
                        [id] => SPEAKERESSENTIALS
                        [title] => Speaker Cables
                    )
                    [SPEAKERSTANDS] => Array (
                        [id] => SPEAKERSTANDS
                        [title] => Speaker Stands
                    )
                    [SPEAKERBRACKETS] => Array (
                        [id] => SPEAKERBRACKETS
                        [title] => Speaker Wall Brackets
                    )
                )
            )
        )
    )
)

解决方案

The example below will not necessarily be more performant (in time or memory requirements) but avoids manually recursing through the structure and shows an easier (IMHO) way to build your desired output array.

function search_in_array($needle, $haystack) {
    $path = array();

    $it = new RecursiveIteratorIterator(
        new ParentIterator(new RecursiveArrayIterator($haystack)),
        RecursiveIteratorIterator::SELF_FIRST
    );

    foreach ($it as $key => $value) {
        if (array_key_exists('id', $value) && strcasecmp($value['id'], $needle) === 0) {
            $path = array($needle);
            for ($i = $it->getDepth() - 1; $i >= 0; $i--) {
                $path = array($it->getSubIterator($i)->key() => $path);
            }
            break;
        }
    }

    return $path;
}

Reference

Bonus

You could also use the RecursiveIteratorIterator::setMaxDepth() method to limit the recursion to n levels deep, if your array also goes much deeper.

这篇关于使用RecursiveArrayIterator获取所有父节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆