使用RecursiveArrayIterator获取所有父节点

Boj*_*les 0 php optimization spl

基本上,我想使用

$foo = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack));
Run Code Online (Sandbox Code Playgroud)

方法,但不是返回一个平面数组foreach()来保持结构,而是只返回一个伟大的大子节点和它的父节点.这可能在PHP?


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

如何使用RecursiveArrayIterator,RecursiveIteratorIterator或做不到这一点,其他内置功能(即尽可能少的自定义代码越好)返回匹配的节点与它的父树从搜索阵列?我想获得最快的功能,因为目前这个功能花费8秒执行14000次,因此我需要使用内置函数.

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Array (
    [HOMECINEMA] => Array (
        [children] => Array (
            [HC-VISION] => Array (
                [children] => Array (
                    [0] => TVALL
                )
            )
        )
    )
)
Run Code Online (Sandbox Code Playgroud)

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

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
                    )
                )
            )
        )
    )
)
Run Code Online (Sandbox Code Playgroud)

sal*_*the 6

下面的示例不一定是更高性能(在时间或内存要求),但避免手动递归通过结构,并显示更容易(恕我直言)的方式来构建您想要的输出数组.

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;
}
Run Code Online (Sandbox Code Playgroud)

参考

奖金

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