【PHP8.x】array_intersect関数の使い方

作成日: 更新日:

array_intersect関数は、複数の配列の中から、すべての配列に共通して存在する値を見つけ出し、新しい配列として返す機能を提供する関数です。この関数はPHPのバージョン8.4で利用できます。

具体的には、最初の配列を基準として、それ以降に指定されたすべての配列に存在する値を検索します。値の比較は、厳密な型比較ではなく、PHPの標準的な比較規則(==演算子に準ずる)に基づいて行われます。例えば、整数5と文字列"5"は等しいと判断される場合があります。この関数は、配列のキーではなく、あくまで値に基づいて共通部分を特定します。

引数には、比較対象となる配列を複数指定します。最低2つの配列が必要です。戻り値としては、すべての配列に共通して含まれる値だけを集めた新しい配列が返されます。この新しい配列のキーは、共通する値が最初の配列で持っていたキーがそのまま保持されます。もし共通する値が一つも存在しない場合は、空の配列が返されます。

この関数は、複数のデータセットから共通の要素を抽出する際に非常に役立ちます。例えば、異なるユーザーグループに共通して存在するアイテムをリストアップしたい場合などに使用できます。キーは比較の対象外であるため、キーも含めて比較したい場合は、関連する別の関数を使用する必要があります。

基本的な使い方

構文(syntax)

<?php
$array1 = ['a' => 'green', 'red', 'blue'];
$array2 = ['b' => 'green', 'yellow', 'red'];
$result = array_intersect($array1, $array2);
print_r($result);
?>

引数(parameters)

array $array, array ...$arrays

  • array $array: 比較対象となる配列
  • array ...$arrays: 比較対象となる追加の配列(可変長引数)

戻り値(return)

array

与えられた配列の全てに存在する値のみを抽出した新しい配列を返します。

サンプルコード

PHP array_intersect_keyで共通キー配列を抽出する

<?php

/**
 * 複数の配列に共通して存在するキーを持つ要素を抽出します。
 *
 * この関数は、最初の配列を基準とし、そのキーが他のすべての配列にも存在する場合に、
 * 最初の配列から対応するキーと値を返します。
 * キーのみが比較され、値は比較されません。
 *
 * @param array $array1 比較の基準となる最初の配列。
 * @param array ...$arrays 比較対象となる1つ以上の追加の配列。
 * @return array 共通のキーを持つ要素からなる配列。
 */
function demonstrateArrayIntersectKey(array $array1, array ...$arrays): array
{
    // array_intersect_keyは、指定されたすべての配列に存在するキーを持つ要素を返します。
    // 値は比較せず、キーのみを比較します。
    // 最初の配列の値が結果として保持されます。
    return array_intersect_key($array1, ...$arrays);
}

// 使用例:
$baseArray = [
    'id' => 101,
    'name' => 'Alice',
    'email' => 'alice@example.com',
    'status' => 'active'
];

$filterArray1 = [
    'id' => 200, // キーは存在するが値は異なる
    'name' => 'Bob',
    'created_at' => '2023-01-01'
];

$filterArray2 = [
    'name' => 'Charlie',
    'email' => 'charlie@example.com',
    'updated_at' => '2023-05-01'
];

// baseArrayとfilterArray1、filterArray2の全てに共通するキーの要素を抽出
$commonKeysResult = demonstrateArrayIntersectKey($baseArray, $filterArray1, $filterArray2);

echo "元の配列1 (基準): \n";
print_r($baseArray);

echo "元の配列2: \n";
print_r($filterArray1);

echo "元の配列3: \n";
print_r($filterArray2);

echo "すべての配列に共通するキーを持つ要素:\n";
print_r($commonKeysResult);

// 期待される出力:
// 'name' はすべての配列に存在するキーなので、$baseArray['name'] が結果に含まれる。
// 'id' は $baseArray と $filterArray1 に存在するが、$filterArray2 には存在しないため、結果には含まれない。
// 'email' は $baseArray と $filterArray2 に存在するが、$filterArray1 には存在しないため、結果には含まれない。
// 結果: Array ( [name] => Alice )

// 別の使用例:
$products = [
    'apple' => ['price' => 100, 'stock' => 50],
    'banana' => ['price' => 50, 'stock' => 100],
    'orange' => ['price' => 80, 'stock' => 70]
];

$availableProducts = [
    'apple' => true,
    'banana' => true,
    'grape' => true
];

$onSaleProducts = [
    'banana' => true,
    'orange' => true,
    'kiwi' => true
];

// products, availableProducts, onSaleProductsの全てに共通するキーを持つ要素を抽出
$filteredProducts = demonstrateArrayIntersectKey($products, $availableProducts, $onSaleProducts);

echo "\n元の商品リスト:\n";
print_r($products);

echo "利用可能な商品 (キーのみ比較):\n";
print_r($availableProducts);

echo "セール中の商品 (キーのみ比較):\n";
print_r($onSaleProducts);

echo "利用可能かつセール中の商品(元の商品の情報):\n";
print_r($filteredProducts);

// 期待される出力:
// 'banana' がすべての配列に共通するキーなので、$products['banana'] が結果に含まれる。
// 結果: Array ( [banana] => Array ( [price] => 50 [stock] => 100 ) )

?>

PHP 8で提供されるarray_intersect_key関数は、複数の配列に共通して存在するキーを持つ要素を抽出するために使用されます。この関数は、最初の配列を基準として、その配列のキーが比較対象となる他のすべての配列にも存在するかどうかを確認します。値そのものは比較せず、キーの名前のみを比較の対象とします。

引数としては、まず比較の基準となる最初の配列を一つ指定します。続いて、比較対象となる追加の配列を複数指定することができます。関数が実行されると、すべての配列に共通して存在するキーを持つ要素が、基準となる最初の配列から抽出されて新しい配列として返されます。したがって、結果として得られる配列には、共通するキーに対応する最初の配列の値が保持されます。例えば、異なる設定ファイルから共通のキーを持つ設定項目を抽出するような場面で、この関数は非常に役立ちます。

この関数は、複数の配列間でキーのみを比較し、それらすべての配列に共通して存在するキーを持つ要素を抽出します。最も重要な注意点は、値は一切比較されないことです。共通のキーが見つかった場合、基準となる最初の配列のキーと値が結果として返されます。キーは一致しても、値が異なっていても結果には影響しません。可変長引数により、複数の配列を同時に比較できます。元の配列は変更されず、共通のキーを持つ要素だけを含む新しい配列が戻り値として生成されますので、コードを安全に利用できます。主に連想配列のキーを比較したい場合に役立ちます。

PHP array_intersect の逆を実装する

<?php

/**
 * 複数の配列の共通部分ではない要素を計算します。
 * これは、全ての入力配列の和集合から、全ての入力配列の共通部分を除外した結果を返します。
 * PHPのarray_intersect関数の「逆」として、いずれかの配列には存在するが、すべての配列には共通しない要素を抽出します。
 *
 * 例:
 * $array1 = [1, 2, 3, 4];
 * $array2 = [3, 4, 5, 6];
 * $array3 = [4, 6, 7, 8];
 *
 * array_intersect($array1, $array2, $array3) は [4] を返します。
 * array_intersect_opposite($array1, $array2, $array3) は [1, 2, 3, 5, 6, 7, 8] を返します。
 *
 * @param array $array 比較する最初の配列
 * @param array ...$arrays 比較する残りの配列群 (可変引数)
 * @return array 共通部分ではない要素の配列
 */
function array_intersect_opposite(array $array, array ...$arrays): array
{
    // 全ての入力配列を一つの配列にまとめる
    $all_input_arrays = array_merge([$array], $arrays);

    // 全ての配列に存在するユニークな要素の集合(和集合)を取得
    // array_merge(...$all_input_arrays) は、PHP 7.4 以降で配列の展開に使用可能
    $union_elements = array_unique(array_merge(...$all_input_arrays));

    // 全ての配列に共通する要素の集合(共通部分)を取得
    $common_elements = array_intersect($array, ...$arrays);

    // 和集合から共通部分を除外した要素を返す(対称差の拡張)
    return array_diff($union_elements, $common_elements);
}

// --- サンプルコード ---

// 数値配列の例
$array1 = [1, 2, 3, 4];
$array2 = [3, 4, 5, 6];
$array3 = [4, 6, 7, 8];

echo "--- 数値配列の例 ---\n";
echo "配列1: " . implode(', ', $array1) . "\n";
echo "配列2: " . implode(', ', $array2) . "\n";
echo "配列3: " . implode(', ', $array3) . "\n";

// array_intersect の結果 (共通要素)
$intersect_result = array_intersect($array1, $array2, $array3);
echo "array_intersect の結果 (共通要素): ";
print_r($intersect_result);
// 期待される出力: Array ( [0] => 4 )

// array_intersect_opposite の結果 (共通ではない要素)
$opposite_result = array_intersect_opposite($array1, $array2, $array3);
echo "array_intersect_opposite の結果 (共通ではない要素): ";
print_r($opposite_result);
// 期待される出力: Array ( [0] => 1 [1] => 2 [2] => 3 [4] => 5 [5] => 6 [6] => 7 [7] => 8 )

// 文字列配列の例
$fruits1 = ['apple', 'banana', 'orange', 'grape'];
$fruits2 = ['banana', 'kiwi', 'orange', 'mango'];
$fruits3 = ['orange', 'grape', 'lemon', 'banana'];

echo "\n--- 文字列配列の例 ---\n";
echo "配列1: " . implode(', ', $fruits1) . "\n";
echo "配列2: " . implode(', ', $fruits2) . "\n";
echo "配列3: " . implode(', ', $fruits3) . "\n";

// array_intersect の結果 (共通要素)
$intersect_fruits = array_intersect($fruits1, $fruits2, $fruits3);
echo "array_intersect の結果 (共通要素): ";
print_r($intersect_fruits);
// 期待される出力: Array ( [1] => banana [2] => orange )

// array_intersect_opposite の結果 (共通ではない要素)
$opposite_fruits = array_intersect_opposite($fruits1, $fruits2, $fruits3);
echo "array_intersect_opposite の結果 (共通ではない要素): ";
print_r($opposite_fruits);
// 期待される出力: Array ( [0] => apple [3] => grape [4] => kiwi [5] => mango [6] => lemon )

?>

array_intersect_opposite関数は、複数の配列が与えられた際に、それら全ての配列に共通して存在する要素ではない要素を計算し、新しい配列として返すカスタム関数です。これは、PHPに標準で備わるarray_intersect関数が「全ての配列に共通する要素」を抽出するのに対し、その「逆」の要素群、つまり「いずれかの配列には存在するが、全ての配列には共通しない要素」を抽出する目的で作成されています。

この関数は、まず比較対象となる最初の配列を$arrayとして受け取ります。その後、比較したい残りの配列を...$arraysとして可変引数でいくつでも受け入れることができます。そして、共通部分ではない要素のみを含む新しい配列を戻り値として返します。

内部的な動作としては、まず全ての入力配列を一つにまとめて重複を取り除いた「和集合」を作成します。次に、array_intersect関数を使用して全ての配列に「共通する要素」の集合を計算します。最終的に、この「和集合」から「共通する要素」の集合を除外することで、目的とする「共通部分ではない要素」の配列を得ています。

例えば、[1, 2, 3, 4][3, 4, 5, 6][4, 6, 7, 8]という3つの数値配列に対しては、array_intersectが共通要素である[4]を返すのに対し、array_intersect_oppositeは共通ではない要素である[1, 2, 3, 5, 6, 7, 8]を返します。また、['apple', 'banana', 'orange', 'grape']['banana', 'kiwi', 'orange', 'mango']['orange', 'grape', 'lemon', 'banana']という文字列配列の場合、array_intersect['banana', 'orange']を、array_intersect_opposite['apple', 'grape', 'kiwi', 'mango', 'lemon']を返します。この関数は、複数のデータセットの中から、それぞれのデータセットに固有の要素や、全てのデータセットには共通しない要素を特定したい場合に非常に役立ちます。

このarray_intersect_opposite関数は、PHPのarray_intersectとは異なり、複数の配列の中から全ての配列に共通しない要素を抽出する自作関数です。PHPに組み込まれている関数ではないため、ご自身のコード内で定義して利用する必要があります。特に、array_merge(...$all_input_arrays)のような配列展開の記法はPHP 7.4以降で有効ですので、ご利用のPHPバージョンにご注意ください。本関数は配列のを比較します。戻り値の配列では、元の配列のキーが引き継がれる場合がありますので、もし連番のインデックスが必要な場合は、結果にarray_values()を適用すると良いでしょう。

【PHP8.x】array_intersect関数の使い方 | いっしー@Webエンジニア