4

假设我有一个这样的数组:

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
4

2 回答 2

2

您遇到的问题涉及递归和/或树遍历。RecursiveArrayIteratorPHP 支持使用和对数组进行树遍历RecursiveIteratorIterator

要获取所有父数组的所有key,需要从第一层到当前深度获取key。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";
}

在这个例子中,首先创建了RecursiveArrayIteratorwith your $array。为了启用树遍历,它被包装到RecursiveIteratorIterator. 这是以递归方式使用$it-iterator所必需的。foreach

foreachthen 内部,将根据您的搜索值检查数组值。如果不匹配,则继续下一个值。

但如果它确实匹配递归迭代器上的getDepth()andgetSubIterator()方法,则用于创建键数组。

该示例执行以下输出:

 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

在您的场景中,您还希望根据特定值(此处为 string "x")过滤迭代器,您可以通过使用RegexIteratorwhich is a轻松完成此操作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

如您所见,它会针对您感兴趣的值进行过滤。

您可能感兴趣的其他相关问题是:

于 2013-03-20T11:14:20.067 回答
2

我目前能想到的唯一方法是大量嵌套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);
            }
        }
    }
}

只是一个承担,不一定工作或类似的东西。

于 2013-02-15T20:05:34.753 回答