假设我有一个这样的数组:
Array
(
[Start] => Array
(
[Item 1] => Array
(
[0] => Item 1_1
[Item 2_1] => Array
(
[Item 2_1_1] => x
)
[1] => Item 3_1
)
[0] => Item 2
[1] => Item 3
)
)
有没有一个php函数可以用来获取指向数组中值x
的路径,也就是说,在这种情况下,结果是:
Start, Item 1, Item 2_1, Item 2_1_1, x
我目前能想到的唯一方法是大量嵌套的foreach ($array as $key => $value)
循环和array_search()
。
不过,最好将其设计为递归函数,因此使用函数是明智的。
function recursiveSearch($key, $array)
{
foreach ($array as $k => $ar) {
if (is_array('x', $ar)) {
return $k . ', ' . array_search('x', $ar);
} else {
if ($ar === 'x') {
return $k
} else {
return recursiveSearch($key, $ar);
}
}
}
}
只是一种尝试,不一定有效或类似的东西。
您遇到的问题涉及递归和/或树遍历。PHP支持使用RecursiveArrayIterator
和RecursiveIteratorIterator
遍历数组的树。
要获取所有父数组的所有关键帧,需要从第一个级别获取到当前深度并获取关键帧。RecursiveIteratorIterator
和getSubIterator()
方法都支持这一点。手册中并没有很好地记录它,所以这里有一个例子:
$it = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array)
);
foreach ($it as $value) {
if ($value !== 'x') continue;
$keys = array();
$depth = $it->getDepth();
for ($i = 0; $keys[] = $it->getSubIterator($i)->key(), $depth--; $i++);
echo implode(', ', $keys), ', ', $value, "n";
}
在本例中,首先创建带有$array
的RecursiveArrayIterator
。为了实现树遍历,它被封装到RecursiveIteratorIterator
中。这对于以递归方式将$it
迭代器与foreach
一起使用是必要的。
然后,在foreach
中,根据搜索值检查数组值。如果不匹配,则继续使用下一个值。
但是,如果它与getDepth()
和getSubIterator()
匹配,则使用递归迭代器上的方法来创建键数组。
该示例执行以下输出:
Start, Item 1, Item 2_1, Item 2_1_1, x
这与你在问题中的描述相匹配。
因为这些都是迭代器,所以您也可以将其实现到自己的类中。以下Iterator
类不仅允许在构造函数中提供的数组上进行树遍历,而且还具有一个名为getKeys()
的方法,该方法返回一个包含从最低级别到当前深度的所有键的数组:
/**
* Class ArrayRecursiveKeysIterator
*/
class ArrayRecursiveKeysIterator extends RecursiveIteratorIterator
{
/**
* @param array $array
*/
public function __construct(array $array)
{
parent::__construct(new RecursiveArrayIterator($array));
}
/**
* @return array keys
*/
public function getKeys()
{
for ($k = [], $i = 0, $m = $this->getDepth(); $i <= $m; $i++)
$k[] = $this->getSubIterator($i)->key();
return $k;
}
}
这样它就更容易使用了(可能也适用于其他场景)。所以首先是一些基本的用法示例。遍历数组,显示每个值的所有键。实例化数组的迭代器,并根据每个值输出键:
$it = new ArrayRecursiveKeysIterator($array);
foreach ($it as $value) {
echo implode(', ', $it->getKeys()), ', ', $value, "n";
}
这将创建以下输出:
Start, Item 1, 0, Item 1_1
Start, Item 1, Item 2_1, Item 2_1_1, x
Start, Item 1, 1, Item 3_1
Start, 0, Item 2
Start, 1, Item 3
在您的场景中,您还希望根据特定值(此处为字符串"x"
)过滤迭代器,通过使用RegexIterator
(FilterIterator
)可以很容易地进行过滤。这就是你的场景:
$it = new ArrayRecursiveKeysIterator($array);
$filter = new RegexIterator($it, '~^x$~');
foreach ($filter as $value) {
echo implode(', ', $it->getKeys()), ', ', $value, "n";
}
这里是输出:
Start, Item 1, Item 2_1, Item 2_1_1, x
正如你所看到的,它是根据你感兴趣的值进行过滤的
你可能感兴趣的其他相关问题有:
- RecursiveIteratorIterator如何在php中工作
- PHP-从面包屑列表的多维关联数组返回父数组
- 以相反的顺序从单向数组中获取数据