Многомерные массивы, вложенные в неограниченную глубину
У меня многомерный массив, вложенный в неизвестную/неограниченную глубину.
Я хотел бы иметь возможность прокручивать каждый элемент.
Я не хочу использовать, foreach(){foreach(){foreach(){}}}
, поскольку я не знаю глубины.
В конечном итоге я ищу все вложенные массивы под названием "xyz
". Кто-нибудь получил какие-либо предложения?
Ответы
Ответ 1
Используя вышеприведенные комментарии, я нашел ответ:
function findXyz($array){
foreach($array as $foo=>$bar){
if (is_array($bar)){
if ($bar["xyz"]){
echo "<br />The array of xyz has now been found";
print_r($bar['xyz']);
}else{
findXyz($bar);
}
}
}
}
findXyz($myarray);
Этот цикл проходит через все вложенные массивы и ищет любой элемент, у которого есть подматрица xyz, в соответствии с моим первоначальным запросом. array_walk_array и RecursiveIteratorIterator не смогли этого добиться.
Ответ 2
В конечном итоге я ищу все вложенные массивы, называемые "xyz". Кто-нибудь получил какие-либо предложения?
Конечно. Основываясь на предложениях по использованию некоторых итераторов, вы можете:
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $key => $item) {
if (is_array($item) && $key === 'xyz') {
echo "Found xyz: ";
var_dump($item);
}
}
Важное различие между другими ответами и тем, что используется флаг RecursiveIteratorIterator::SELF_FIRST
, чтобы отображать не-листовые (т.е. родительские) элементы (т.е. массивы), видимые при итерации.
Вы также можете использовать ParentIterator
вокруг итератора массива, а не проверять массивы в цикле, чтобы сделать последнее немного более аккуратным.
Ответ 3
Рекурсия.
Напишите функцию, которая перемещает один массив; для каждого элемента, который также является массивом, он называет себя; в противном случае, когда он найдет целевую строку, она вернется.
Ответ 4
Существует огромная разница между неизвестным и неограниченным. Тем не менее, вы можете использовать Итераторы SPL вместо использования нескольких вложенных циклов foreach
.
Пример:
$array_obj = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach($array_obj as $key => $value) {
echo $value;
}
Ответ 5
Посмотрите на RecursiveIteratorIterator интерфейс.
$interface = new RecursiveIteratorIterator( new RecursiveArrayIterator($your_array) );
foreach($interface as $k=>$v) { /* your function*/ }
Ответ 6
Задумывались ли вы об использовании array_walk_recursive для этого?
Другой (более медленный) подход заключался бы в сгладить массив перед выполнением поиска, то есть:
$myarray = array('a','b',array(array(array('x'),'y','z')),array(array('p')));
function array_flatten($array,$return)
{
for($x = 0; $x <= count($array); $x++)
{
if(is_array($array[$x]))
{
$return = array_flatten($array[$x],$return);
}
else
{
if($array[$x])
{
$return[] = $array[$x];
}
}
}
return $return;
}
$res = array_flatten($myarray,array());
Или, для рекурсивного поиска, см. здесь для примера:
function arrayRecursiveSearch($needle, $haystack, $path=""){
if(!is_array($haystack)){
die("second argument is not array");
}
global $matches;
foreach($haystack as $key=>$value)
{
if(preg_match("/$needle/i", $key)){
$matches[] = array($path . "$key/", "KEY: $key");
}
if(is_array($value)){
$path .= "$key/";
arrayRecursiveSearch($needle, $value, $path);
unset($path);
}else{
if(preg_match("/$needle/i", $value)){
$matches[] = array($path . "$key/", "VALUE: $value");
}
}
}
return $matches;
}
$arr = array("Asia"=>array('rambutan','duku'),
"Australia"=>array('pear','kiwi'),
"Arab"=>array('kurma'));
print_r(arrayRecursiveSearch("ra",$arr));