填充PHP数组:首先检查索引?

时间:2008-10-03 20:16:50

标签: php optimization readability

如果我深陷在一个循环巢中,我想知道哪一个更有效:

if (!isset($array[$key])) $array[$key] = $val;

$array[$key] = $val;

就可读代码而言,第二种形式更为可取。实际上,名称更长,数组是多维的。因此,第一个表格在我的程序中看起来非常粗糙。

但我想知道第二种形式是否会变慢。由于代码是程序中最常执行的函数之一,我想使用更快的形式。

一般来说,此代码将使用相同的“$ key”值执行多次。所以在大多数情况下,$ array [$ key]已经设置好了,而且isset()将返回FALSE。

澄清那些担心我将不相同的代码视为相同的人:就程序的这一部分而言,$ val是一个常数。直到运行时才知道它,但它在程序的早期设置,并且在此处不会更改。因此两种形式都会产生相同的结果。这是获得$ val的最方便的地方。

9 个答案:

答案 0 :(得分:10)

对于您真正想要的数组:array_key_exists($key, $array)而不是isset($array[$key])

答案 1 :(得分:3)

isset()使用普通变量非常快,但这里有一个数组。数组的哈希映射算法很快,但它仍然比不采取任何操作需要更多的时间。

现在,如果您设置了更多的值,那么第一个表单可以更快,而不是因为它只是查找哈希而不提取或设置值。所以,这可能是一个不同之处:如果您在设置的键上有更多“命中”,则选择第一个表单,如果您有更多“未命中”,则选择第二个表单。

请注意,这两段代码相同。某个键已经设置时,第一个表单不会设置该值 - 它可以防止'覆盖'。

答案 2 :(得分:2)

您是否测量过在尝试设置$array[$key]之前遇到$array[$key]的情况?我认为人们无法对此提出一般性建议,因为如果实际上存在很多这样的情况,那么通过避免数组上的不合理集合,isset check可能会节省一些时间。但是,如果这种情况很少发生,那么开销可能会让你失望......最好的办法就是对你的实际代码进行基准测试。

但请注意,两个代码都会导致不同的结果!如果$val组合的$ val并不总是相同,则前一代码将始终将值设置为$array[$key]的第一个$val,其中后一个代码将始终将其设置为该组合的最后一个值。

(我想您已经注意到这一点$array[$key] {{1}}总是相同的,但有些读者可能不会这样做。)

答案 3 :(得分:1)

比较的开销可能会或可能不是真的似乎需要更长的时间。

两种配置中运行脚本的性能时间是什么?

答案 4 :(得分:1)

您应该检查数组,但不包括您要设置的级别。

如果您要设置

$anArray[ 'level1' ][ 'level2' ][ 'level3' ] = ...

在设置level3之前,您应该确保达到level2的路径确实存在。

$anArray[ 'level1' ][ 'level2' ]

如果不这样,小狗实际上不会被杀死,但根据您的特定环境,他们可能会生气。

您不必检查您实际设置的索引,因为自动设置它意味着它已被声明,但为了良好实践,您应该确保没有任何神奇的创建。

有一种简单的方法可以做到这一点:

<?php

function create_array_path( $path, & $inArray )
{
    if ( ! is_array( $inArray ) )
    {
        throw new Exception( 'The second argument is not an array!' );
    }
    $traversed = array();
    $current = &$inArray;

    foreach( $path as $subpath )
    {
        $traversed[] = $subpath;
        if ( ! is_array( $current ) )
        {
            $current = array();
        }
        if ( ! array_key_exists( $subpath, $current ) )
        {
            $current[ $subpath ] = '';
        }
        $current = &$current[ $subpath ];
    }
}


$myArray = array();

create_array_path( array( 'level1', 'level2', 'level3' ), $myArray );

print_r( $myArray );

?>

这将输出:

    Array
    (
        [level1] => Array
            (
                [level2] => Array
                    (
                        [level3] => 
                    )

            )

    )

答案 5 :(得分:0)

对isset()的额外函数调用几乎可以保证比任何赋值都有更多的开销。如果第二种形式不快,我会非常惊讶。

答案 6 :(得分:0)

您是否需要进行实际检查以查看密钥是否存在?通过分配空白数组,isset()只会减慢循环速度。除非你使用数据操作进行第二次传递,否则我强烈建议不要使用isset检查。这是人口,而不是操纵。

答案 7 :(得分:0)

我是PHP的新手,但两者的结合可能是三元运算符

$array[$key] = !isset($array[$key]) ? $val : $array[$key];

这是一种方法。

答案 8 :(得分:0)

您可以查看PHP源代码以查看差异。没有检查在PHP的更高版本中这是否会有所不同,但在PHP3中,关联数组功能似乎在php3/php3_hash.c中。

在函数_php3_hash_exists中,完成以下操作:

  • 键是哈希
  • 找到正确的存储桶
  • 桶走了,直到找到正确的项目

功能_php3_hash_add_or_update:

  • 散列
  • 发现
  • bucket
  • 走了,现有被覆盖如果存在的话
    • 如果不存在,则添加新的

因此,它似乎只是设置它更快,因为只有一个函数调用,这个散列和存储桶查找业务只会完成一次。