array_unique
配列を渡すだけで重複している要素を削除してくれるとっても便利な関数です。しかし、値が文字列にキャスト可能な1次元の配列にしか適用できないという制約があります。これをカスタムするための関数を作ってみましょう。
array_unique_callback
array_filter
を static変数 と絡めて使用するのがネックです。
function array_unique_callback(array $array, callable $callback, $strict = false) {
return array_filter(
$array,
function ($item) use ($callback, $strict) {
static $h = array();
$r = !in_array($n = $callback($item), $h, $strict) and $h[] = $n;
return $r;
}
);
}
- PHPにありそうな感じの名前にしました。
- PHP5.3では callable タイプヒンティングを外してください。
-
isset
を用いて $O(1)$ の探索時間を実現しても良かったのですが、今回はスカラー値以外も比較に使用できるようにin_array
を使う実装にしました。
下に使用例を示します。
PHPコード
<?php
$companies = array(
0 => array(
'name' => 'やずや',
'phone' => '0120-828-828',
'category' => 'サプリメント',
),
1 => array(
'name' => 'DHC',
'phone' => '0120-575-3709',
'category' => 'サプリメント',
),
2 => array(
'name' => 'KIRIN',
'phone' => '0120-111-560',
'category' => 'お酒',
),
);
$companies = array_unique_callback(
$companies,
function ($company) {
return $company['category'];
}
);
print_r($companies);
実行結果
Array
(
[0] => Array
(
[name] => やずや
[phone] => 0120-828-828
[category] => サプリメント
)
[2] => Array
(
[name] => KIRIN
[phone] => 0120-111-560
[category] => お酒
)
)
作ってみたものの・・・
ぶっちゃけこれぐらい関数化しなくても普通にシンプルに書けるからいらないかも・・・w
連想配列のキーに格納する方法だと、代入式
$h[$c['category']] = true
が必ず TRUE と評価されるのでここまで短く書ける。
$companies = array_filter(
$companies,
function ($c) {
static $h;
return !isset($h[$c['category']]) and $h[$c['category']] = true;
}
);