检查数组是否存在于多维数组中 - 无循环 - 未知深度

时间:2012-01-25 20:48:09

标签: php arrays search multidimensional-array

我需要进行快速查找以查找数组中是否存在数组。如果我知道阵列的深度它会很容易 - 而且速度很快!

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

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

如果你不知道深度,你会如何动态地做到这一点?在每个级别进行循环和搜索对于我的应用来说太慢了。

2 个答案:

答案 0 :(得分:1)

你的问题已经答案了:

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"]);

答案 1 :(得分:0)

你需要一些类型的循环,但你不需要遍历整个深度。您可以简单地使用相当于$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

你需要加入一些防御机制来使函数更加健壮(对于不存在的元素/索引),但这是基本的方法。