PHPを用いてアプリケーションを開発する際、配列の操作は避けて通れない重要なトピックです。
特に配列から特定の要素を削除する処理は、データの整理やフィルタリングにおいて頻繁に利用されます。
PHPには要素を削除するための手段が複数用意されていますが、代表的なものにunset関数とarray_splice関数があります。
これら二つの関数は、削除後の配列の状態に大きな違いがあるため、用途に応じて正しく使い分ける必要があります。
本記事では、初心者の方から実務で活用したい方まで役立つよう、配列要素の削除手法を詳しく解説します。
unset関数で特定の要素を削除する
unset関数は、指定した変数を破棄するための関数であり、配列の特定のキーを指定して要素を削除できます。
この関数の最大の特徴は、削除した要素のインデックス(添字)がそのまま保持されるという点です。
つまり、削除された箇所のインデックスは「歯抜け」の状態になり、後ろにある要素が自動的に前に詰められることはありません。
unset関数の基本的な使い方
まずは、unset関数を使用して数値添字配列から要素を削除する基本的な例を見てみましょう。
<?php
// 数値添字配列の定義
$fruits = ["apple", "banana", "cherry"];
// インデックス1(banana)を削除
unset($fruits[1]);
// 配列の中身を表示
print_r($fruits);
?>
Array
(
[0] => apple
[2] => cherry
)
実行結果を確認すると、インデックス「1」の要素が消え、インデックス「0」と「2」が残っていることがわかります。
このように、特定のキーを狙い撃ちして消去したい場合にunsetは非常に便利です。
連想配列での利用シーン
unset関数は、キーが文字列である連想配列においても同様に利用可能です。
連想配列の場合は、インデックスの順序を気にする必要が少ないため、unsetが最も一般的な削除手段となります。
<?php
$user = [
"id" => 1,
"name" => "田中",
"email" => "tanaka@example.com"
];
// emailの情報を削除
unset($user["email"]);
print_r($user);
?>
Array
(
[id] => 1
[name] => 田中
)
特定のユーザープロフィールから特定の項目だけを動的に削除したい場合などに重宝します。
array_splice関数で要素を削除して詰め直す
数値添字配列において、要素を削除した後にインデックスを0から順番に振り直したい場合は、array_splice関数を使用します。
この関数は配列の一部を削除し、必要に応じて他の要素で置換するためのものですが、削除専用としても機能します。
array_splice関数の基本的な使い方
array_spliceを使用して、先ほどの例と同じようにインデックス1の要素を削除してみましょう。
<?php
$fruits = ["apple", "banana", "cherry"];
// インデックス1から1つの要素を削除
array_splice($fruits, 1, 1);
print_r($fruits);
?>
Array
(
[0] => apple
[1] => cherry
)
実行結果を見ると、削除された「banana」の後ろにあった「cherry」のインデックスが「2」から「1」へと自動的に繰り上がっていることがわかります。
for文などのループ処理で配列の添字を順番に参照する必要がある場合は、この挙動が非常に重要になります。
複数要素の一括削除
array_spliceの第3引数を調整することで、指定した位置から複数の要素を一度に削除することも可能です。
<?php
$numbers = [0, 1, 2, 3, 4, 5];
// インデックス2から3つの要素(2, 3, 4)を削除
array_splice($numbers, 2, 3);
print_r($numbers);
?>
Array
(
[0] => 0
[1] => 1
[2] => 5
)
このように、範囲を指定して効率的に配列を整理できるのがarray_spliceの強みです。
unsetとarray_spliceの違いと比較
どちらの関数を使用すべきか迷ったときは、削除後のインデックスをどう扱いたいかを基準に考えます。
以下の表に、主な違いをまとめました。
| 特徴 | unset | array_splice |
|---|---|---|
| インデックスの振り直し | なし(歯抜けになる) | あり(自動で詰める) |
| 連想配列への対応 | 推奨(キーで指定) | 非推奨(位置で指定) |
| 破壊的な変更 | はい(元の配列を書き換える) | はい(元の配列を書き換える) |
| 戻り値 | なし(void) | 削除された要素の配列 |
もし数値添字配列をunsetで削除した後に、やはりインデックスを詰めたいと思った場合は、array_values関数を併用することで解決できます。
$fruits = ["apple", "banana", "cherry"];
unset($fruits[1]);
// インデックスを振り直す
$fruits = array_values($fruits);
しかし、最初から詰めることが分かっているならば、array_spliceを使う方がスマートなコードになります。
条件に基づいて要素を削除する(array_filter)
インデックスやキーを指定するのではなく、「値が〇〇である要素をすべて消したい」という場合にはarray_filter関数が適しています。
array_filterは、コールバック関数を用いて配列の各要素をテストし、条件に一致するものだけを残す(あるいは取り除く)ことができます。
<?php
$data = [10, 20, 30, 40, 50];
// 30以上の要素だけを残す(30未満を削除するのと同義)
$result = array_filter($data, function($value) {
return $value >= 30;
});
print_r($result);
?>
Array
(
[2] => 30
[3] => 40
[4] => 50
)
注意点として、array_filterもunsetと同様に元のインデックスを保持します。
新しい配列としてインデックスを振り直したい場合は、再度array_valuesを通す必要があります。
配列の先頭や末尾を削除する専用関数
配列の特定の箇所の削除に特化した関数も存在します。
これらはスタックやキューといったデータ構造を扱う際に非常に便利です。
array_pop(末尾を削除)
配列の最後の要素を取り除きたいときは、array_popを使用します。
$stack = ["orange", "banana", "apple"];
$last_item = array_pop($stack);
// $stack は ["orange", "banana"] になる
array_shift(先頭を削除)
配列の最初の要素を取り除きたいときは、array_shiftを使用します。
この関数は削除後、数値インデックスを自動的に振り直してくれます。
$queue = ["first", "second", "third"];
$first_item = array_shift($queue);
// $queue は ["second", "third"] になり、インデックスは0から始まる
多次元配列の要素削除
複雑なデータ構造である多次元配列でも、基本的には同じ手法が使えます。
削除したい階層までキーを指定して、unsetを実行するだけです。
<?php
$users = [
["id" => 1, "name" => "田中"],
["id" => 2, "name" => "佐藤"]
];
// 最初のユーザーのname要素だけを削除
unset($users[0]["name"]);
print_r($users);
?>
このように、階層が深くなってもドット記法のような指定ではなく、配列のブラケットを繋げて指定することで削除が可能です。
よくあるエラーと注意点
配列の要素を削除する際に最も多い間違いは、ループの中で不用意に要素を削除することです。
特にforeachループ内でunsetを使用すると、ループの挙動に影響を与えたり、存在しないインデックスを参照しようとしてエラーが発生する原因になります。
安全に削除を行うためには、削除したい要素のキーを一時的な配列に保存しておき、ループの外で一括削除するか、array_filterを活用することをお勧めします。
また、存在しないキーに対してunsetを実行してもエラー(Notice)は発生しませんが、可読性の観点からはarray_key_existsなどで存在確認を行うのが丁寧です。
まとめ
PHPで配列の要素を削除する方法は、その後の配列構造をどう維持したいかによって決まります。
特定のキーを削除し、インデックスを維持したい場合や連想配列の場合は、unset関数を使用するのがベストです。
一方で、数値添字配列で削除後に隙間を詰めたい場合は、array_splice関数を選択しましょう。
また、条件に応じた一括削除にはarray_filter、末尾や先頭の削除にはarray_popやarray_shiftといった専用関数を使い分けるのが効率的です。
それぞれの関数の特性を正しく理解し、バグの少ないクリーンなコードを目指してください。
