【php】配列から、重複している要素、1個しかない要素を探す
問題
ある配列の要素の中から、重複している要素だけを探したり、1個しかない重複していない要素を探したりしたいです。

答え
わかりやすくはないかもしれないけど1行でできなくもなかった。
以下は、array_filterを使った例。
重複した要素を探す
$data = array(1, 2, 2, 3, 4, 4, 5, 7, 10, 20, 10, 4);
$res = array_filter(array_count_values($data), function($v){return --$v;});
//PHP5.2 以前の場合
$res = array_filter(array_count_values($data), create_function('$v', 'return --$v;'));
array(3) {
[2]=>
int(2)
[4]=>
int(3)
[10]=>
int(2)
}
重複してない要素を探す
$data = array(1, 2, 2, 3, 4, 4, 5, 7, 10, 20, 10, 4);
$res = array_filter(array_count_values($data), function($v){return !--$v;});
//PHP5.2 以前の場合
$res = array_filter(array_count_values($data), create_function('$v', 'return !--$v;'));
array(5) {
[1]=>
int(1)
[3]=>
int(1)
[5]=>
int(1)
[7]=>
int(1)
[20]=>
int(1)
}
・結果は、キーに値、値に重複した数となります。値の方が欲しいときは、さらに array_keys などする。
・評価する配列内の値の型は考慮していません。数値と文字列の同一値( 2 と "2" 等)がある場合、array_count_valuesによって重複と判断されます。
array_count_valuesで重複値をカウントし、それに対してarray_filterしている。
array_filterのcallbackで --$v してるのは、1(つまり重複してない)の場合は0になってreturnされるのでfalse扱い。2以上(つまり重複してる)の場合は1以上になってtrue扱い。
重複してない要素を探すときは、returnする値を ! して逆転させている。
別解
array_filterやcallbackを使わない版
$data = array(1, 2, 2, 3, 4, 4, 5, 7, 10, 20, 10, 4);
//配列の中で1個しかない要素
$res = array_keys(array_count_values($data), 1);
var_dump($res);
/*
array(3) {
[1]=>
int(2)
[4]=>
int(4)
[8]=>
int(10)
}
*/
//配列の中で1個しかない要素じゃないもの = 重複している要素
$res = array_unique(array_diff($data, array_keys(array_count_values($data), 1)));
var_dump($res);
/*
array(5) {
[0]=>
int(1)
[1]=>
int(3)
[2]=>
int(5)
[3]=>
int(7)
[4]=>
int(20)
}
*/