diesel
diesel

Reputation: 3415

Notice: Undefined index when trying to increment an associative array in PHP

I'm trying to increment the value for $variable each time a duplicate variable occurs. I'm not sure if this is syntactically correct, but I think this is semantically correct. var_dump seems to spit out the correct outputs, but i get this error: Notice: Undefined index...

$newarray = array();
foreach ($array as $variable)
{
    $newarray[$variable]++; 
    var_dump($newarray);
}

$array = (0 => h, 1 => e, 2 => l, 3=> l, 4=> o);

goal:

'h' => int 1
'e' => int 1
'l' => int 2
'o' => int 1

My code works, it's just that I get some weird NOTICE.

Upvotes: 5

Views: 8103

Answers (8)

thunberg
thunberg

Reputation: 31

This takes advantage of the fact that references accept undefined variables and PHP silently creates them:

$_ = &$lookup_with_long_name[$key_with_long_name] xor $_ += $value_with_long_name;

This only uses the lookup, key, and value variables once each, and sets if undefined and increments if defined, all without throwing a warning (or eventually an error in PHP 9)

xor operator works because PHP always has to evaluate both sides.

Make sure to unset($_) when you're done.

Upvotes: 0

Tilman Vogel
Tilman Vogel

Reputation: 9773

I really like mickmackusa's use of null coalesce in

$new = [];
foreach ($array as $v) {
    $new[$v] ??= 0;
    ++$new[$v];
}

but you can save the second lookup using an array element reference which automatically inserts a null element if not present:

$new = [];
foreach ($array as $v) {
    $entry =& $new[$v];
    ++$entry;
}

Luckily, the increment operator considers null to be zero and increments to 1 as desired.

Upvotes: 0

mickmackusa
mickmackusa

Reputation: 47894

In modern PHP, you can avoid the isset() call by leveraging the null coalescing operator. In the snippet below, the technique sets the variable to 0 if the variable is not yet declared. Then you can freely use a range of shorthand manipulations such as concatenation, arithmetic, etc.

$new = [];
foreach ($array as $v) {
    $new[$v] = ($new[$v] ?? 0) + 1;
}

Or if you want to continue using ++, then you can use the "null coalescing assignment operator". The logic on the right side of assignment is not even executed if the variable is already declared. The below snippet will perform identically to the above snippet.

$new = [];
foreach ($array as $v) {
    $new[$v] ??= 0;
    ++$new[$v];
}

As for your sample data and desired result of letters and counts, I'd probably use a fully native, functional approach. (Demo)

var_export(
    array_count_values(str_split('hello'))
); // letters are in the same order as they were encountered

Much less attractive technique for the same result:

$assoc = count_chars('hello', 1);
var_export(
    array_reduce(
        array_keys($assoc),
        fn($result, $k) => $result += [chr($k) => $assoc[$k]],
        []
    )
); // letters are alphabetized

Upvotes: 3

Your Common Sense
Your Common Sense

Reputation: 157863

$newarray = array();
foreach ($array as $variable)
{
    if (!isset($newarray[$variable])) {
        $newarray[$variable] = 0;
    }
    $newarray[$variable]++;
}

Upvotes: 10

Hailwood
Hailwood

Reputation: 92581

$newarray = array();
foreach ($array as $variable)
{
    if(!isset($newarray[$variable]))
      $newarray[$variable] = 0;

      $newarray[$variable]++; 
    var_dump($newarray);
}

Upvotes: 0

VolkerK
VolkerK

Reputation: 96159

<?php
$newarray = array();
foreach ($array as $variable) {
    if ( !array_key_exists($variable, $newarray) ) {
        $newarray[$variable] = 0;
    }
    ++$newarray[$variable];
}
var_dump($newarray);

But you could also use array_count_values() instead.

Upvotes: 1

codaddict
codaddict

Reputation: 455030

Take a look at the function array_count_values(). It does exactly what you are trying to do.

Sample from php.net:

$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));

Result:

Array
(
    [1] => 2
    [hello] => 2
    [world] => 1
)

Upvotes: 3

Mark Cameron
Mark Cameron

Reputation: 2369

You are incrementing the wrong thing, try this instead:

foreach ($array as $key => $variable) {
   $array[$key]++; 
   var_dump($array);
}

Upvotes: -2

Related Questions