Многомерные массивы, вложенные в неограниченную глубину

У меня многомерный массив, вложенный в неизвестную/неограниченную глубину. Я хотел бы иметь возможность прокручивать каждый элемент. Я не хочу использовать, 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));