1. ホーム
  2. PHP

【PHP】array_diff・array_intersect の使い方|配列の差分・共通部分を求める

Share

2つの配列を比べて「片方にしかない値」や「両方に共通する値」を取り出したいことがあります。PHP では array_diff() で差分を、array_intersect() で共通部分を簡単に求められます。この記事では、これらの基本的な使い方と、キーも比較する array_diff_assoc() などの仲間、つまずきやすいポイントまでをコード例つきで解説します。

array_diff() で差分(引き算)を求める

array_diff() は、第1引数の配列から、ほかの配列に含まれる値を取り除いた結果を返します。「A から B にある値を引く」イメージです。元の配列は変更せず、新しい配列を返します。

array_diff.php
<?php
$all     = ['apple', 'banana', 'orange', 'grape'];
$ordered = ['banana', 'grape'];

// $all から $ordered にある値を取り除く
$remaining = array_diff($all, $ordered);

print_r($remaining);
// Array
// (
//     [0] => apple
//     [2] => orange
// )

結果の配列では、元のキー(上の例では 02)がそのまま保持される点に注意してください。連番に振り直したいときは、後述の array_values() を使います。第3引数以降にも配列を渡せ、それらすべてに含まれない値だけが残ります。

array_intersect() で共通部分を求める

array_intersect() は逆に、すべての配列に共通して含まれる値だけを返します。「AND(かつ)」の関係で、複数の配列に共通する要素を抜き出したいときに使います。

array_intersect.php
<?php
$userRoles     = ['editor', 'author', 'subscriber'];
$allowedRoles  = ['administrator', 'editor', 'author'];

// 両方に含まれる値だけを取り出す
$matched = array_intersect($userRoles, $allowedRoles);

print_r($matched);
// Array
// (
//     [0] => editor
//     [1] => author
// )

こちらも第1引数のキーが保持されます。ユーザーが持つ権限のうち、許可リストに含まれるものだけを抜き出す、といった用途で役立ちます。

値の比較方法と仲間の関数

array_diff()array_intersect() は「値」だけを比較します。比較は文字列に変換して行われるため、数値の 1 と文字列の "1" は同じとみなされます。キーも合わせて比較したい場合や、キーだけで比較したい場合は、用途に応じた仲間の関数が用意されています。

関数比較するもの
array_diff() / array_intersect()値のみ
array_diff_assoc() / array_intersect_assoc()キーと値の両方
array_diff_key() / array_intersect_key()キーのみ

たとえば連想配列で「キーと値のペアが一致するもの」を比べたいときは _assoc 版を使います。次の例で挙動の違いを確認できます。

assoc.php
<?php
$a = ['name' => 'Sato', 'age' => 30, 'city' => 'Tokyo'];
$b = ['name' => 'Sato', 'age' => 25, 'city' => 'Tokyo'];

// キーと値の両方で比較。age だけ値が違うので差分になる
$diff = array_diff_assoc($a, $b);

print_r($diff);
// Array
// (
//     [age] => 30
// )

実践例:追加・削除された項目を見つける

array_diff() をうまく使うと、変更前と変更後の2つのリストを比べて「追加されたもの」と「削除されたもの」を同時に求められます。引く順番を入れ替えるのがポイントです。

changes.php
<?php
$before = ['html', 'css', 'php'];
$after  = ['html', 'css', 'javascript'];

// after にあって before に無い → 追加された
$added   = array_values(array_diff($after, $before));
// before にあって after に無い → 削除された
$removed = array_values(array_diff($before, $after));

print_r($added);   // Array ( [0] => javascript )
print_r($removed); // Array ( [0] => php )

ここでは array_values() で結果のキーを 0 から振り直しています。タグの編集差分や、設定項目の変更検出などに応用できます。

思った結果にならないとき

キーが連番に戻らない

これらの関数は元の配列のキーを保持するため、結果は [0, 2, 5] のような飛び飛びのキーになることがあります。foreach で回すだけなら問題ありませんが、0 から順番のキーが欲しいときや json_encode() で配列として出力したいときは、array_values() でキーを振り直してください。

オブジェクトや配列を含むと警告が出る

array_diff()array_intersect() は値を文字列に変換して比較します。そのため、要素にオブジェクトや配列が含まれていると「配列を文字列に変換できない」といった警告が出て、正しく比較できません。多次元配列を比較したい場合は、比較したい値を取り出してから渡すか、用途に合わせて自分でループを書く必要があります。

まとめ

array_diff()array_intersect() は、2つ以上の配列を比べるときの基本となる関数です。

  • array_diff() は第1引数からほかの配列にある値を取り除く(差分)
  • array_intersect() はすべての配列に共通する値を返す(共通部分)
  • キーも比較したいなら _assoc 版、キーだけなら _key 版を使う
  • 引く順番を入れ替えれば「追加」「削除」を同時に求められる
  • 結果のキーは保持されるので、必要に応じて array_values() で振り直す

リスト同士の比較は自分でループを書きがちですが、これらの関数を使えば1行で書けてミスも減ります。差分や共通部分を求めたくなったら、まずこの2つを思い出してみてください。

参考ページ