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

私が現在考えることができる唯一の方法は、と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 に答える
2

あなたが抱えている問題には、再帰および/またはツリートラバーサルが含まれます。RecursiveArrayIteratorPHP は、およびを使用した配列のツリー トラバーサルをサポートしています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";
}

この例では、まずRecursiveArrayIteratorwith your$arrayを作成します。ツリー トラバーサルを有効にするために、 にラップされますRecursiveIteratorIterator。これは、$it-iterator を と一緒にforeach再帰的に使用するために必要です。

then内foreachで、配列値が検索値に対してチェックされます。一致しない場合は、次の値に進みます。

ただし、一致する場合は、再帰反復子の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") に基づいてイテレータをフィルタリングすることも必要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

ご覧のとおり、関心のある値でフィルター処理されています。

おそらく関心のあるその他の関連する質問は次のとおりです。

于 2013-03-20T11:14:20.067 に答える