PHP:对于计数器的关联数组,在第一次增量之前显式地将每个值初始化为0是否更习惯?


PHP: with an associative array of counters, is it more idiomatic to explicitly initialize each value to 0 before the first increment?

我正在编写一些构建计数器关联数组的代码。当它第一次遇到新项时,它创建一个新键并将其初始化为0。例如:

if (!array_key_exists($item, $counters)) {
    $counters[$item] = 0;
}
$counters[$item]++;
然而,PHP实际上隐式地完成了第一部分。
 $counters[$item]++;

…那么$counters[$item]将计算为NULL,并在增加之前转换为0。显然,第二种方法更简单、更简洁,但感觉有点俗气,因为它不明显地表明$counters[$item]可能还不存在。在PHP中哪一种方式更受欢迎?

进行比较,在Python中惯用的方法是使用集合。计数器,当你想要将键初始化为0时;一个常规字典,当你想要自己初始化它们时。在PHP中,你只有第一个选项

增加未初始化的键将生成PHP通知,这是一个坏主意。你应该先初始化。

然而,array_key_exists的使用并不十分习惯。我知道从Python来看,这可能看起来很自然,但是如果你知道$counter没有有意义的NULL值,那么使用isset()来测试数组成员是更习惯的。(我也不知道为什么它要快得多!)

以下是我在PHP中编写计数器的方法:
$counters = array();
foreach ($thingtobecounted as $item) {
    if (isset($counters[$item])) {
        $counters[$item]++;
    } else {
        $counters[$item] = 1;
    }
}

不幸的是,与Python不同,PHP没有提供任何不执行两次键查找的方法。

首选。第二个选项将在日志中生成一个通知,说明$counters[$item]未定义。它仍然有效,但如果你改变display_errors = On;和error_reporting = E_ALL。在php.ini文件中,您将在浏览器中看到这些通知:

第一种方法通常是您如何做的,如果只是为了更简单的维护。请记住,您可能不是维护代码的人。您不希望错误日志充斥着正确的操作代码。更糟糕的是,您可能需要将方法转移到其他语言(或更早版本的PHP),这些语言可能不会进行隐式初始化。

如果您真的不需要检查每个数组索引—或者知道大多数索引将是未定义的—为什么不抑制如下错误呢?

(这样可以在初始化[无用]索引时节省一些性能)

if (@!array_key_exists($item, $counters)) {