LoginSignup
41
13

More than 3 years have passed since last update.

配列要素を削除するとインデックスが残ったり残らなかったりする

Posted at

PHPの配列は、キーのインデックスなどが配列側でしっかり管理されています。

$a = [];
$a[] = 1;
$a[10] = 2;
$a[] = 3;

var_dump($a); // [0=>1, 10=>2, 11=>3]

キーを空白にすると、自動的に次のインデックスを割り当ててくれます。
とても便利。

しかしこのインデックス、一度増えるとその後値を消しても戻りません。

$a = [0, 1];

unset($a[1]);
$a[] = 2;

var_dump($a); // [0=>0, 2=>2]

せっかく配列の最後の値を消したのに、使用した情報は残っていて次のキーは2になっています。
MySQLのauto_increment値と同様、一度上限が上がると下がらないということです。
全ての値を消したとしても同様です。

$a = [0, 1];

unset($a[1]);
unset($a[0]);
$a[] = 2;

var_dump($a); // [2=>2]

ところでこいつを見てくれ。

$a = [0, 1];

unset($a[1]);
unset($a[0]);
$b = $a;

$a[] = 2;

var_dump($a); // [0=>2] ←

$b=$aと配列をコピーしたらインデックスの記憶が消え、また0から始まるようになりました。
なんでだよ。

さらにこっちも見てくれ。

$a = [0, 1];

unset($a[1]);
unset($a[0]);
$b = $a;

$a[] = 2;
$b[] = 3;

var_dump($a); // [0=>2]
var_dump($b); // [2=>3] ←

消えたと思っていたインデックスは、実はコピー先の$bに移っていたようです。
なんでだよ。

ところでNormalize arrays' "auto-increment" value on copy on writeというRFCが提出されているのですが、これは配列のコピーの仕組みを変えようという内容です。
具体的には配列のコピーを、以下のコードと同じにします。

$array_copy = [];
foreach($array as $key => $value){
    $array_copy[$key] => $value;
}

このRFCが適用されたらどうなるかというと、

$a = [0, 1];

unset($a[1]);
unset($a[0]);

$b = [];
foreach($a as $k=>$v){
    $b[$k] = $v;
}

$a[] = 2;
$b[] = 3;

var_dump($a); // [2=>2]
var_dump($b); // [0=>3]

解決してなくない?

41
13
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
13