【问题标题】:Checking if array exists within multidimensional array - no looping - unknown depth检查多维数组中是否存在数组 - 无循环 - 未知深度
【发布时间】:2012-02-19 01:39:46
【问题描述】:

我需要进行快速查找以查找数组中是否存在数组。如果我知道数组的深度,这将是简单且快速的!

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

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

如果您不知道深度,您将如何动态执行此操作?对于我的应用程序来说,每个级别的循环和搜索都太慢了。

【问题讨论】:

  • 您想检查$heystack[$var1][$var2][$var3] 是否是一个数组?喜欢使用is_array($heystack[$var1][$var2][$var3])
  • 如果你不知道元素的深度/位置,你可以试试RecursiveArrayIterator
  • 不知道深度是不是不知道 $var1 2 和 3 的位置?
  • 也许对你来说in_array()(允许在数组中搜索数组)会有所帮助...关于深度...数组中的所有数组是否具有相同的深度?

标签: php arrays search multidimensional-array


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    你的问题已经有了答案:

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

    【讨论】:

    • 我只想提一下 isset($heystack[$var1][$var2][$var3] 对于具有键 $var1 和 $var2 但没有 $var3 的给定数组将失败。相反,$var3 将转换为字符串,这将返回 $var2 中值的第一个字符。因此 isset 将返回 true 但 $key3 不存在! // 用于了解深度和键 if(is_array($heystack [$var1][$var2]) && isset($heystack[$var1][$var2][$var3])) ...
    • 当元素存在但设置为null时,实际上isset也会返回false。这是常见的警告。您为错误实现 substring access 可能发生的问题提供了解决方案,对于 isset 问题,它是 array_key_exists
    猜你喜欢
    • 2021-01-13
    • 1970-01-01
    • 2019-04-01
    • 1970-01-01
    • 2015-06-30
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    相关资源
    最近更新 更多