Проверка наличия массива в многомерном массиве - без зацикливания - неизвестная глубина - PullRequest
1 голос
/ 26 января 2012

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

$heystack['lev1']['lev2']['lev3'] = 10; // $heystack stores 10,000s of arrays like this

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

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

Ответы [ 2 ]

2 голосов
/ 26 января 2012

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

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

Если вы не знаете, сколько у вас $var1 ... $varN, вы можете сделать это только динамически, что включает в себя либо циклы, либо 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"]);
0 голосов
/ 26 января 2012

Вам понадобится некоторый вид зацикливания, но вам не нужно будет пересекать всю глубину. Вы можете просто использовать функцию, которая эквивалентна $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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...