Проверка наличия массива в многомерном массиве – отсутствие цикла – неизвестная глубина

Мне нужно сделать быстрый поиск, чтобы найти массив в массиве. Если бы я знал глубину массива, было бы легко и быстро!

$heystack['lev1']['lev2']['lev3'] = 10; // $heystack stores 10,000s of arrays like this if(isset($heystack[$var1][$var2][$var3])) do something... 

Как бы вы сделали это динамически, если вы не знаете глубину? цикл и поиск на каждом уровне будут слишком медленными для моего приложения.

У вашего вопроса уже есть ответ:

 if (isset($heystack[$var1][$var2][$var3])) { # do something... } 

Если вы не знаете, сколько $var1 ... $varN вас есть, вы можете делать это только динамически, что связано с циклом или eval и зависит от того, нужно ли вам иметь дело со строковыми или числовыми ключами. Об этом уже спрашивали и отвечали:

  • Loop и Eval: использовать строки для доступа (потенциально большие) многомерные массивы (и это только одна из многих)

Если вас беспокоит скорость, например, если массив всегда один и тот же, но вам нужно часто его запрашивать, сначала создайте индекс с составными ключами, чтобы вы могли более легко его запросить. Это может быть сделано путем сохранения всех ключей при рекурсивном перемещении массива:

 class CompoundKeys extends RecursiveIteratorIterator { private $keys; private $separator; public function __construct($separator, RecursiveIterator $iterator, $mode = RecursiveIteratorIterator::SELF_FIRST, $flags = 0) { $this->separator = $separator; parent::__construct($iterator, $mode, $flags); } public function current() { $current = parent::current(); if (is_array($current)) { $current = array_keys($current); } return $current; } public function key() { $depth = $this->getDepth(); $this->keys[$depth] = parent::key(); return implode('.', array_slice($this->keys, 0, $depth+1)); } } 

Применение:

 $it = new CompoundKeys('.', new RecursiveArrayIterator($array)); $compound = iterator_to_array($it, 1); isset($compound["$var1.$var2.$var3"]); 

В качестве альтернативы это можно сделать, пройдя рекурсивно и ссылаясь на исходные значения массивов:

 /** * create an array of compound array keys aliasing the non-array values * of the original array. * * @param string $separator * @param array $array * @return array */ function array_compound_key_alias(array &$array, $separator = '.') { $index = array(); foreach($array as $key => &$value) { if (is_string($key) && FALSE !== strpos($key, $separator)) { throw new InvalidArgumentException(sprintf('Array contains key ("%s") with separator ("%s").', $key, $separator)); } if (is_array($value)) { $subindex = array_compound_key_alias($value, $separator); foreach($subindex as $subkey => &$subvalue) { $index[$key.$separator.$subkey] = &$subvalue; } } else { $index[$key] = &$value; } } return $index; } 

Применение:

 $index = array_compound_key_alias($array); isset($index["$var1.$var2.$var3"]); 

Вам понадобится какой- то цикл, но вам не нужно проходить всю глубину. Вы можете просто использовать функцию, которая выполняет эквивалент $heystack[$var1][$var2][$var3] , но динамически:

 $heystack['lev1']['lev2']['lev3'] = 10; echo getElement($heystack, array('lev1', 'lev2', 'lev3')); // you could build second parameter dynamically function getElement($array, $indexes = array()) { foreach ($indexes as $index) { $array = $array[$index]; } return $array; } // output: 10 

Вам нужно будет задействовать некоторые защитные механизмы, чтобы сделать функцию более надежной (для элементов / индексов, которые не существуют), но это основной подход.