PHP: What value array key needs to have to cause next numeric key assignment?

58 views Asked by At

In other words, what value can be assigned to $key so that the following two lines create exactly the same result:

$arr[] = $value;
$arr[$key] = $value;

The task I need to solve looks like the following: I need to add a new value to an array using either the key if specified, or next available numeric key if key is not specified:

protected $_arr;

...
public function addValue($value, $key = NULL) {

    $this->_arr[$key] = $value;

}

Working solutions is like this:

public function addValue($value, $key = NULL) {

    if($key === NULL) $this->_arr[] = $value;
    else $this->_arr[$key] = $value;
}

I suspect there is no such value for the key as I tried obvious NULL and '' (empty string), and neither brings desired result.

2

There are 2 answers

3
Destroy666 On

There's currently no way to set array $key as something that would automatically increment the number key index.

Even the $arr[] = 'value'; syntax doesn't do what you exactly wrote - it doesn't find "next available numeric key", it instead increments the highest found number. Example:

$test = [];
$test[] = 'test0';
$test['666'] = 'test666';
$test[] = 'test1';
var_dump($test);

Results in:

array(3) {
  [0]=>
  string(5) "test0"
  [666]=>
  string(7) "test666"
  [667]=>
  string(5) "test1"
}

To fill all the gaps, you'd need to use an algorithm that finds them - e.g. one that stores the last used numeric index, then increments it and checks if the index is free until it finds next free one.

And if you don't need to fill the gaps, your shown solution is what I'd just use.

0
mickmackusa On

The way you've written your method doesn't see ridiculous, but it is not PSR-12 compliant. I'd write it with curly braces to surround the conditional branches as: (Demo)

public function addValue($value, $key = null): void
{
    if ($key !== null) {
        $this->_arr[$key] = $value;
    } else {
        $this->_arr[] = $value;
    }
}

I'll offer 3 more different approaches -- all which assume that all keys to ever exist in $_arr will be integers.

You can use a null coalescing approach to fallback to a calculation based on the last key in the array, but the risk of using array_key_last() is that there is the potential to accidentally overwrite data when no key is supplied. (Demo)

public function addValue($value, $key = null): void
{
    $this->_arr[$key ?? ((array_key_last($this->_arr) ?? -1) + 1)] = $value;
}

If you want to avoid the potential for unintentionally overwriting elements, then you'll need to either find the "highest" key and increment that. (Demo)

public function addValue($value, $key = null): void
{
    if ($key !== null) {
        $this->_arr[$key] = $value;
    } elseif (!$this->_arr) {
        $this->_arr[] = $value;
    } else {
        $this->_arr[max(array_keys($this->_arr)) + 1] = $value;
    }
}

OR you could iterate the array and search for the earliest missing key and use that for the new value. (Demo)

public function addValue($value, $key = null): void
{
    if ($key !== null) {
        $this->_arr[$key] = $value;
    } else {
        for ($i = 0, $count = count($this->_arr); $i <= $count; ++$i) {
            if (!key_exists($i, $this->_arr)) {
                $this->_arr[$i] = $value;
                break;
            }
        }
    }
}