Alex
Alex

Reputation: 245

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

I'm writing some code that builds up associative array of counters. When it encounters a new item for the first time it creates a new key and initializes it to zero. I.e.:

if (!array_key_exists($item, $counters)) {
    $counters[$item] = 0;
}
$counters[$item]++;

However, PHP actually does that first part implicitly. If I just do...

 $counters[$item]++;

... then $counters[$item] will evaluate to NULL and be converted to 0 before it's incremented. Obviously the second way is simpler and more concise, but it feels a little sleazy because it's not obvious that $counters[$item] might not exist yet. Is one way or the other preferred in PHP?

For comparison, in Python the idiomatic approach would be to use collections.Counter when you want keys that initialize themselves to 0, and a regular dictionary when you want to initialize them yourself. In PHP you only have the first option.

Upvotes: 2

Views: 799

Answers (4)

Francis Avila
Francis Avila

Reputation: 31621

Incrementing an uninitialized key will generate a PHP Notice, and is a bad idea. You should always initialize first.

However, the use of array_key_exists is not very idiomatic. I know coming from Python it may seem natural, but if you know that $counter has no meaningful NULL values it's more idiomatic to use isset() to test for array membership. (It's also much faster for no reason I can discern!)

This is how I would write a counter in PHP:

$counters = array();
foreach ($thingtobecounted as $item) {
    if (isset($counters[$item])) {
        $counters[$item]++;
    } else {
        $counters[$item] = 1;
    }
}

Unfortunately unlike Python PHP does not provide any way to do this without performing two key lookups.

Upvotes: 4

djot
djot

Reputation: 2947

If you don't really need a check on each array index - or know that most of the indexes will be undefinded - why not suppress errors like: ?

(this way you save some performance on initializing [useless] indexes)

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

Upvotes: -1

David R.
David R.

Reputation: 280

The first way is generally how you do it, if for nothing other than simpler maintenance. Remember, you may not be the one maintaining the code. You don't want error logs riddled with correctly operating code. Even worse, you may need to transfer methods to other languages (or earlier versions of PHP) where implicit initialization might not occur.

Upvotes: 2

Mircea Soaica
Mircea Soaica

Reputation: 2817

the first is preferred. the second option will generate a Notice in your logs that $counters[$item] is undefined. it still works but if you change display_errors = On; and error_reporting = E_ALL. in your php.ini file you will see these notices in your browser.

Upvotes: 3

Related Questions