1. ホーム
  2. PHP

【PHP】array_unique で配列の重複を削除する方法|array_count_values・array_values も解説

Share

配列の中に同じ値が何度も入っていて、重複を1つにまとめたい場面はよくあります。PHP では array_unique を使えば、配列から重複した要素を取り除いた新しい配列を簡単に得られます。この記事では array_unique の基本的な使い方と、キーがそのまま残る仕様、第2引数で比較方法を切り替える方法を解説します。あわせて、各値が何回出てきたかを数える array_count_values と、キーを 0 から振り直す array_values も紹介します。

array_unique で重複を取り除く

array_unique は、配列から重複した値を取り除いた配列を返す関数です。元の配列を書き換えるのではなく、重複を除いた新しい配列を戻り値として返します。同じ値が複数あった場合は、最初に出てきた要素だけが残ります。

index.php
<?php
$fruits = ['apple', 'banana', 'apple', 'orange', 'banana'];

$result = array_unique($fruits);

print_r($result);
// Array
// (
//     [0] => apple
//     [1] => banana
//     [3] => orange
// )

結果を見ると、重複していた 2 つ目以降の applebanana が消えています。ここで注目したいのが、残った要素のキーです。orange のキーが 2 ではなく 3 のままになっています。これは array_unique が、元の配列のキーをそのまま保持するためです。

array_values でキーを 0 から振り直す

先ほどのように array_unique の結果はキーが飛び飛びになります。これを 0 から始まる連番に振り直したいときは、array_values を使います。array_values は、配列の値だけを取り出して、キーを 0, 1, 2, … と振り直した配列を返す関数です。

index.php
<?php
$fruits = ['apple', 'banana', 'apple', 'orange', 'banana'];

// 重複を除いてから、キーを振り直す
$result = array_values(array_unique($fruits));

print_r($result);
// Array
// (
//     [0] => apple
//     [1] => banana
//     [2] => orange
// )

このように array_unique の戻り値を array_values で包むと、キーが 0 から続く整然とした配列になります。foreach で値だけを順に処理する場合はキーが飛んでいても問題ありませんが、json_encode で JSON 配列にしたいときや、インデックスを順番に使いたいときは振り直しておくと扱いやすくなります。

第2引数 flags で比較方法を変える

array_unique は第2引数で「値をどう比較して重複と判定するか」を指定できます。指定できる定数は次の4つで、省略した場合は SORT_STRING が使われます。

フラグ比較のしかた
SORT_STRING値を文字列に変換してから比較する(既定値)
SORT_REGULAR型変換をせず、通常の比較(== と同じ規則)で比較する
SORT_NUMERIC値を数値に変換してから比較する
SORT_LOCALE_STRING現在のロケールに従って文字列として比較する

既定の SORT_STRING は値をいったん文字列にしてから見比べます。そのため、数値の 1 と文字列の "1" は同じ値とみなされます。一方 SORT_REGULAR は型変換を行わない通常比較なので、同じデータでも結果が変わることがあります。

index.php
<?php
$values = [1, '1', 2, '2'];

// 既定(SORT_STRING):'1' は "1" として 1 と同じ扱いになる
print_r(array_unique($values));
// Array
// (
//     [0] => 1
//     [2] => 2
// )

// SORT_REGULAR:1 と '1' を数値の 1 とみなし、やはり重複扱いになる
print_r(array_unique($values, SORT_REGULAR));
// Array
// (
//     [0] => 1
//     [2] => 2
// )

この例ではどちらのフラグでも同じ結果になりますが、扱う値の組み合わせ次第で差が出ます。文字列として比較してほしいのか、数値として比較してほしいのかを意識して、必要に応じてフラグを指定しましょう。

array_count_values で出現回数を数える

「重複を消す」のではなく「それぞれの値が何回出てきたか」を知りたいこともあります。そんなときは array_count_values が便利です。この関数は、配列の各値をキーに、その出現回数を値に持つ連想配列を返します。

index.php
<?php
$fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];

$counts = array_count_values($fruits);

print_r($counts);
// Array
// (
//     [apple]  => 3
//     [banana] => 2
//     [orange] => 1
// )

結果を見れば、apple が 3 回、banana が 2 回、orange が 1 回登場したことが一目で分かります。アンケートの集計や、ログの中で同じ項目が何件あったかを数えるといった用途にそのまま使えます。なお array_count_values が数えられるのは、配列の中身が文字列か整数のときだけです。それ以外の型が含まれていると警告が出て、その要素は無視されます。

多次元配列に array_unique を使うとき

array_unique は既定で値を文字列に変換して比較します。要素が配列(多次元配列)の場合、文字列に変換しようとすると Array to string conversion という警告が発生し、すべての要素が同じ文字列 "Array" とみなされてしまいます。その結果、最初の要素だけが残るおかしな挙動になります。

要素が配列の場合は、第2引数に SORT_REGULAR を指定します。これなら文字列変換を行わず、配列同士を通常比較で見比べるため、中身が同じ配列を重複として除けます。

index.php
<?php
$rows = [
    ['id' => 1, 'name' => 'apple'],
    ['id' => 2, 'name' => 'banana'],
    ['id' => 1, 'name' => 'apple'],
];

// SORT_REGULAR なら配列同士を比較できる
$result = array_unique($rows, SORT_REGULAR);

print_r($result);
// id=1 の重複した行が取り除かれる

ただし、特定のキー(たとえば id)だけを基準に重複を判定したい場合は、array_unique だけでは対応できません。その場合は foreach で見たキーを記録しながら絞り込むなど、自前の処理を書く必要があります。

意図せず要素が消えてしまうとき

「重複していないはずなのに要素が減ってしまった」という場合、原因の多くは既定の SORT_STRING による文字列比較です。前述のとおり、数値の 0 と文字列の "0"、あるいは整数の 10 と文字列の "10" は、文字列に直すと同じになるため重複扱いになります。型を区別したいときは SORT_REGULAR を指定するか、比較前に型をそろえておきましょう。

また、array_unique は値そのものを比べるだけで、キーは考慮しません。連想配列に対して使った場合でも、残るのは「最初に現れた要素」であり、どのキーが残るかは元の並び順で決まる点も覚えておくと混乱しません。

まとめ

重複の扱いに関する3つの関数を振り返ります。

  • array_unique は重複を除いた配列を返し、元のキーはそのまま保持される
  • キーを 0 から振り直したいときは array_values で包む
  • 既定の比較は SORT_STRING(文字列比較)で、"1"1 が同じ扱いになる点に注意する
  • 多次元配列に使うときは第2引数に SORT_REGULAR を指定する
  • 出現回数を数えたいときは array_count_values を使う

まずは array_values(array_unique($arr)) の形を覚えておけば、多くの場面で困りません。比較方法でつまずいたら、第2引数のフラグを思い出してみてください。

参考ページ