あなたが抱えている問題には、再帰および/またはツリートラバーサルが含まれます。RecursiveArrayIterator
PHP は、およびを使用した配列のツリー トラバーサルをサポートしています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";
}
この例では、まずRecursiveArrayIterator
with 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
ご覧のとおり、関心のある値でフィルター処理されています。
おそらく関心のあるその他の関連する質問は次のとおりです。