基本上,我想使用
$foo = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack));
方法论,但不是为foreach()
返回一个平面数组,而是保留结构,但只返回一个伟大的子孙节点及其父节点。这可能在PHP吗?
我的任务是优化我公司的一些(可怕的)代码库。我发现了一个通过数组递归,搜索密钥的函数。我无法用简单的array_search()
或array_key_exists()
替换它,因为自定义函数还返回匹配(找到)键的父节点,而不仅仅是{{ 1}}或true
。
如何使用false
,RecursiveArrayIterator
或者使用其他内置函数(即尽可能少的自定义代码)来从搜索数组中返回匹配节点的父树?我想获得最快的功能,因为目前这个函数花费8秒执行14000次,因此我需要使用内置函数。
我现有的尝试(下面)速度非常慢。
RecursiveIteratorIterator
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
)
)
)
)
)
答案 0 :(得分:6)
下面的示例不一定具有更高的性能(在时间或内存要求中),但避免在结构中手动递归,并显示更容易(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
级别。