5

如果我深陷于循环嵌套中,我想知道其中哪一个更有效:

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

或者

$array[$key] = $val;

就可读代码而言,第二种形式更可取。实际上,名称更长,数组是多维的。所以第一种形式最终在我的程序中看起来很粗糙。

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

一般来说,这段代码会以相同的“$key”值执行多次。所以在大多数情况下 $array[$key] 已经被设置,并且 isset() 将返回 FALSE。

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

4

9 回答 9

10

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

于 2008-10-03T20:49:58.540 回答
3

isset() 对普通变量非常快,但是这里有一个数组。数组的哈希映射算法很快,但仍然比什么都不做要花费更多的时间。

现在,如果您设置了更多的值,那么第一种形式可能会比没有设置的值更快,这仅仅是因为它只是在不获取或设置值的情况下查找哈希。因此,这可能是一个不同点:如果您在设置的键上有更多“命中”,则选择第一种形式,如果您有更多“未命中”,则选择第二种形式。

请注意,这两段代码并不相同。第一种形式在已经设置时不会设置某个键的值 - 它可以防止“覆盖”。

于 2008-10-03T20:40:52.347 回答
2

$array[$key]在尝试设置之前,您是否测量过您遇到设置的情况的频率?我认为对此无法给出一般性建议,因为如果实际上有很多这样的情况,则 isset 检查可能会通过避免数组上不必要的集合来节省一些时间。但是,如果这种情况很少发生,那么开销可能会减慢您的速度……。最好的办法是对您的实际代码进行基准测试。

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

(我想你知道这一点并且$val对于 总是相同的$array[$key],但有些读者可能不会。)

于 2008-10-03T20:45:21.810 回答
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] => 
                    )

            )

    )
于 2009-01-28T12:31:08.420 回答
1

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

在两种配置中运行脚本对性能时间有何影响?

于 2008-10-03T20:18:13.393 回答
0

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

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

这是一种方法。

于 2008-10-03T20:53:45.693 回答
0

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

于 2008-10-03T20:22:30.153 回答
0

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

于 2008-10-03T20:46:49.730 回答
0

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

在函数_php3_hash_exists中,做了以下事情:

  • 密钥被散列
  • 找到正确的存储桶
  • 桶走,直到找到正确的项目

函数_php3_hash_add_or_update:

  • 散列
  • 找到存储桶
  • 行走,如果存在则覆盖现有
    • 如果不存在,则添加新的

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

于 2008-10-06T17:53:21.123 回答