配列から「先頭の3件だけ欲しい」「途中の要素を取り除きたい」「特定の位置に値を差し込みたい」——こうした操作でよく登場するのが array_slice() と array_splice() です。名前が1文字違いでよく似ていますが、片方は元の配列を変えずに一部を取り出す関数、もう片方は元の配列を直接書き換えて削除・差し替え・挿入する関数で、性質はまったく違います。この記事では2つの違いをはっきりさせながら、offset や length の負数指定、preserve_keys、置換用の引数まで、実際に動くコードで解説します。配列操作にまだ慣れていない初心者〜中級者の方が対象です。
目次
取り出す array_slice、書き換える array_splice
まず押さえておきたいのは、この2つが「非破壊」か「破壊的」かという根本的な違いです。array_slice() は配列の一部を切り出して新しい配列として返すだけで、渡した元の配列には手を付けません。一方 array_splice() は元の配列そのものを書き換え、要素を取り除いたり別の値に差し替えたりします。そして取り除いた(抜き出した)要素を戻り値として返します。
| 関数 | 元の配列 | 戻り値 | 主な用途 |
|---|---|---|---|
array_slice() | 変えない(非破壊) | 切り出した部分の配列 | 一部を取り出す |
array_splice() | 書き換える(破壊的) | 取り除いた要素の配列 | 削除・差し替え・挿入 |
「元のデータを残したまま一部を見たい」なら array_slice()、「配列の中身を編集したい」なら array_splice()、と覚えると選び分けに迷いません。以降で、それぞれの具体的な使い方を見ていきます。
array_slice で一部を取り出す
array_slice() は array_slice($array, $offset, $length, $preserve_keys) の形で呼び出します。$offset は切り出しを始める位置(0 始まり)、$length は取り出す個数です。$length を省略すると、$offset から末尾まですべてを取り出します。
<?php
$fruits = ["りんご", "みかん", "ぶどう", "もも", "なし"];
// 2番目(index 1)から3個を取り出す
$result = array_slice($fruits, 1, 3);
print_r($result);
// Array ( [0] => みかん [1] => ぶどう [2] => もも )
// 元の配列はそのまま(非破壊)
print_r($fruits);
// Array ( [0] => りんご [1] => みかん [2] => ぶどう [3] => もも [4] => なし )
戻り値を見ると分かるとおり、デフォルトでは取り出した配列のキーは 0 から振り直されます。$fruits 自体は一切変わっていない点も確認してください。これが「非破壊」の意味です。
offset と length に負の数を使う
$offset と $length には負の数も指定できます。$offset が負なら「末尾から数えた位置」から切り出し、$length が負なら「末尾から数えてその手前まで」を取り出します。末尾の数件だけ欲しいときに便利です。
<?php
$nums = [10, 20, 30, 40, 50];
// 末尾から2件を取り出す
print_r(array_slice($nums, -2));
// Array ( [0] => 40 [1] => 50 )
// 先頭から、末尾の1件を除いたところまで
print_r(array_slice($nums, 0, -1));
// Array ( [0] => 10 [1] => 20 [2] => 30 [3] => 40 )
preserve_keys で元のキーを残す
第4引数 $preserve_keys を true にすると、切り出した要素の元の数値キーを保ったまま取り出せます(デフォルトは false=0 から振り直す)。なお文字列キー(連想配列のキー)は、この引数に関係なく常に保持されます。
<?php
$nums = [10, 20, 30, 40, 50];
// 振り直し(デフォルト)
print_r(array_slice($nums, 2, 2));
// Array ( [0] => 30 [1] => 40 )
// 元のキー(2, 3)を保持
print_r(array_slice($nums, 2, 2, true));
// Array ( [2] => 30 [3] => 40 )
array_splice で削除する
ここからは array_splice() です。呼び出し方は array_splice($array, $offset, $length, $replacement) で、第1引数は参照渡しになっており、関数を呼ぶとその配列が直接書き換わります。$replacement(置換用の値)を渡さなければ、$offset から $length 個の要素を削除します。戻り値は、取り除かれた要素の配列です。
<?php
$fruits = ["りんご", "みかん", "ぶどう", "もも", "なし"];
// index 1 から2個を取り除く
$removed = array_splice($fruits, 1, 2);
print_r($removed);
// Array ( [0] => みかん [1] => ぶどう ) ← 取り除かれた要素
print_r($fruits);
// Array ( [0] => りんご [1] => もも [2] => なし ) ← 元の配列が変わっている
削除後、残った要素のキーは自動的に詰められて 0 から振り直されます。unset($fruits[1]) でも要素は消せますが、その場合はキーに欠番(穴)ができます。キーを詰めて連番のまま削除したいときは array_splice() が向いています。
array_splice で差し替え・挿入する
第4引数 $replacement に値(配列でも単一の値でもよい)を渡すと、取り除いた部分にその値を差し込みます。これで「差し替え」と「挿入」の両方が表現できます。
要素を差し替える
削除する個数($length)と差し込む値を両方指定すれば、その範囲を新しい値に置き換えられます。削除する個数と差し込む個数は同じである必要はなく、たとえば1個を2個に増やすこともできます。
<?php
$colors = ["red", "green", "blue"];
// index 1 の1個を、2つの値に差し替える
array_splice($colors, 1, 1, ["yellow", "orange"]);
print_r($colors);
// Array ( [0] => red [1] => yellow [2] => orange [3] => blue )
削除せずに挿入する
$length に 0 を指定すると、何も削除せずに $offset の位置へ値を割り込ませます。つまり「指定位置への挿入」になります。配列の途中に要素を加えたいときの定番テクニックです。
<?php
$items = ["A", "B", "C"];
// index 1 の位置に "X" を挿入(削除はしない)
array_splice($items, 1, 0, ["X"]);
print_r($items);
// Array ( [0] => A [1] => X [2] => B [3] => C )
引数の組み合わせで挙動が変わるので、よく使うパターンを表で整理しておきます。
| やりたいこと | length | replacement |
|---|---|---|
| 削除 | 削除する個数 | 渡さない |
| 差し替え | 削除する個数 | 差し込む値 |
| 挿入 | 0 | 差し込む値 |
元の配列が変わってしまうときの確認ポイント
「配列を加工したつもりが、元のデータまで変わってしまった」というトラブルは、たいてい array_slice() と array_splice() を取り違えたことが原因です。原因を切り分けるポイントを2つ挙げます。
取り出すだけのつもりが splice を使っている
一部を読み取りたいだけなら、必ず array_slice() を使います。array_splice() は第1引数を参照渡しで受け取り、呼んだ瞬間に元の配列を書き換えます。「結果を別の変数で受け取っているから安全」と思っても、元の配列はすでに変わっている点に注意してください。元データを残したいときは array_slice() か、事前に配列をコピーしておきましょう。
戻り値の意味が逆だと勘違いしている
2つの関数は、戻り値が指すものが正反対です。array_slice() の戻り値は「取り出した(残したい)部分」ですが、array_splice() の戻り値は「取り除かれた部分」で、編集後の本体は元の配列のほうに残ります。array_splice() の戻り値を「編集後の配列」だと思って使うと、結果がずれてしまいます。編集後の中身は第1引数に渡した変数を見る、と覚えておきましょう。
まとめ
名前が似ている2つの関数ですが、役割を整理すると迷わず使い分けられます。要点を振り返ります。
array_slice()は非破壊。元の配列を変えず、一部を新しい配列として取り出すarray_splice()は破壊的。元の配列を直接書き換え、取り除いた要素を返すoffsetとlengthは負数も使え、末尾基準の指定ができるarray_splice()はreplacementの指定で差し替え、lengthを0にすれば挿入になる
「読み取りたいだけなら slice、中身を編集したいなら splice」を出発点に、負数指定や挿入・差し替えへ広げていけば、配列の前後の切り出しから途中の編集まで一通りこなせるようになります。