SlideShare a Scribd company logo
PHP
array_uintersectに潜む罠
array_intersect
配列の共通項を計算する
配列の共通項を計算する
$arr1 = ['foo', 'bar', 'baz'];
$arr2 = ['foo', 'baz'];
array_intersect($arr1, $arr2);
// ['foo', 'baz']
注意
二つの要素は、
(string) $elem1 === (string) $elem2 の場合のみ
等しいとみなされます。
言い換えると、文字列表現が同じ場合となります。
多次元配列の比較ができない
そこでarray_uintersect
配列の共通項を計算する(コールバック)
配列の共通項を計算する(コールバック)
$arr1 = [
['key' => 'foo'],
['key' => 'bar'],
['key' => 'baz'],
];
$arr2 = [
['key' => 'foo'],
['key' => 'baz'],
];
array_uintersect($arr1, $arr2, $someFunc);
// [['key' => 'foo'], ['key' =>'baz']]
比較関数について
比較関数は、
最初の引数と二番目の引数の比較結果を返します。
最初の引数のほうが二番目の引数より大きい場合は正の数を、
二番目の引数と等しい場合はゼロを、
そして二番目の引数より小さい場合は負の数を返す
必要があります。
???
比較?比較ナンデ?
0のとき等しい、俺は詳しいんんだ
$someFunc = function($a, $b) {
if ($a['key'] === $b['key']) {
return 0;
}
};
array_uintersect($arr1, $arr2, $someFunc);
グワーッ!!
$someFunc = function($a, $b) {
if ($a['key'] === $b['key']) {
return 0;
}
};
array_uintersect($arr1, $arr2, $someFunc);
// [
// ['key' => 'foo'],
// ['key' => 'bar'],
// ['key' => 'baz'],
// ]
罠1: 関数はきちんと書くべし
せいかいのかきかた
$someFunc = function($a, $b) {
if ($a['key'] === $b['key']) {
return 0;
}
if ($a['key'] > $b['key']) {
return 1;
}
return -1;
};
結構応用できるのでは?
部分一致を試してみる
$someFunc = function($a, $b) {
if (strpos($a, $b) !== false) {
return 0;
}
if ($a > $b) {
return 1;
}
return -1;
};
部分一致を試してみる
$arr1 = ['foo', 'bar', 'bazfoo', 'fooqux'];
$arr2 = ['foo'];
array_uintersect($arr1, $arr2, $someFunc);
グワーッ!!
$arr1 = ['foo', 'bar', 'bazfoo', 'fooqux'];
$arr2 = ['foo'];
array_uintersect($arr1, $arr2, $someFunc);
// [
// 'bazfoo',
// ]
罠2: 内部では
入力をソートしている
かつごうったってそうはいかねえ
$someFunc = function($a, $b) {
echo "{$a} <=> {$b}" . PHP_EOL;
if ($a == $b) {
return 0;
}
if ($a > $b) {
return 1;
}
return -1;
};
かつごうったってそうはいかねえ
$arr1 = [1, 3, 5];
$arr2 = [2, 4];
array_uintersect($arr1, $arr2, $someFunc);
グワーッ!!
3 <=> 1
5 <=> 3
4 <=> 2
1 <=> 2
3 <=> 2
3 <=> 2
3 <=> 4
5 <=> 4
5 <=> 4
グワーッ!!
3 <=> 1
5 <=> 3
4 <=> 2
// 明らかに入力をソートしている
1 <=> 2
3 <=> 2
3 <=> 2
3 <=> 4
5 <=> 4
5 <=> 4
……どうしてこんなことするの
多分計算量節約のため。
……どうしてこんなことするの
多分計算量節約のため。
入力をソートする初期コストはかかるが、
ソート済み配列を辿るならば
自分より小さいまたは一致する要素の次に
自分より大きい要素が来た場合、
それ以上辿っても自分と一致する要素はないことがわかる。
……どうしてこんなことするの
多分計算量節約のため。
入力をソートする初期コストはかかるが、
ソート済み配列を辿るならば
自分より小さいまたは一致する要素の次に
自分より大きい要素が来た場合、
それ以上辿っても自分と一致する要素はないことがわかる。
これにより全要素対全要素の比較をしなくてよくなり、
特に要素が多い場合の計算量が抑えられる。
……どうしてこんなことするの
多分計算量節約のため。
入力をソートする初期コストはかかるが、
ソート済み配列を辿るならば
自分より小さいまたは一致する要素の次に
自分より大きい要素が来た場合、
それ以上辿っても自分と一致する要素はないことがわかる。
これにより全要素対全要素の比較をしなくてよくなり、
特に要素が多い場合の計算量が抑えられる。
比較関数が完全でないといけない理由は、
最初のソートに使うため。
つまりは
こんなことには使えない:
一致の有無がソート順では判断できない場合。
ex. 文字列の部分一致
こんなことには使える:
一致の有無がソート順で判断できる場合。
ex. 文字列の前方一致
罠を知って楽しい
array_uintersectライフを!

More Related Content

PDF
20170401 alias
PDF
みんなで Swift 復習会 GO! in 岩手 – 9th′
PPTX
詳説ぺちぺち
ODP
本当は怖いPHP
PDF
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswift
PDF
アルゴリズム+データ構造勉強会(8)
KEY
Elixir macro-in-action-1
ODP
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
20170401 alias
みんなで Swift 復習会 GO! in 岩手 – 9th′
詳説ぺちぺち
本当は怖いPHP
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswift
アルゴリズム+データ構造勉強会(8)
Elixir macro-in-action-1
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜

What's hot (20)

PDF
俺のフックがこんなに簡単なわけがない。
PDF
Elixirだ 第2回
PDF
C++11概要 ライブラリ編
PDF
Elixirだ 第1回 - 基礎だ -
PDF
Swift らしい表現を目指そう #eventdots
PPTX
PHPのタイプヒンティング
PDF
Elixirだ 第1回強化版 後半
PDF
Elixirだ 第1回強化版 前半
PDF
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
ODP
Ekmett勉強会発表資料
PDF
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
PDF
"What Does Your Code Smell Like?"で学ぶPerl6
PDF
Ekmett勉強会発表資料
KEY
モナドがいっぱい!
PDF
Ruby 同好会宣言
PPTX
F#のすすめ
PDF
40分濃縮 PHP classの教室
PDF
すごいH 第12章モノイド
PDF
Hachiojipm #5 LT資料 [テーマ:最近いいなと思ったもの]
PPTX
PHP基本的関数QUIZ
俺のフックがこんなに簡単なわけがない。
Elixirだ 第2回
C++11概要 ライブラリ編
Elixirだ 第1回 - 基礎だ -
Swift らしい表現を目指そう #eventdots
PHPのタイプヒンティング
Elixirだ 第1回強化版 後半
Elixirだ 第1回強化版 前半
Swift 3 で新しくなったところ - 表面から見えにくいところを中心に紹介 #ISAOcorp
Ekmett勉強会発表資料
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
"What Does Your Code Smell Like?"で学ぶPerl6
Ekmett勉強会発表資料
モナドがいっぱい!
Ruby 同好会宣言
F#のすすめ
40分濃縮 PHP classの教室
すごいH 第12章モノイド
Hachiojipm #5 LT資料 [テーマ:最近いいなと思ったもの]
PHP基本的関数QUIZ
Ad

Viewers also liked (11)

PDF
Profile vps solar pakistan 2016
DOCX
LED DOWN LIGHT
PPT
Proposta
PPT
4 principles of_spirituality
PDF
Hello adele
ODP
blogs
ODP
Mysql(クライアント)の出力が変わるオプション達
PPTX
2016 st 12f
PPTX
2016 st 9f
Profile vps solar pakistan 2016
LED DOWN LIGHT
Proposta
4 principles of_spirituality
Hello adele
blogs
Mysql(クライアント)の出力が変わるオプション達
2016 st 12f
2016 st 9f
Ad

More from Takaaki Hirano (20)

ODP
プログラミング言語のマスコットとか紹介
ODP
金曜だけどデザインパターンでも勉強しよう
ODP
非同期データ更新のためにメッセージキューを導入した(い)話
ODP
月曜だからデザインパターンでも勉強しよう vol.4 Builder
ODP
月曜だからデザインパターンでも勉強しよう vol.3 Factory Method & Abstract Factory
ODP
月曜だからデザインパターンでも勉強しよう vol.2 Flyweight
ODP
月曜だからデザインパターンでも勉強しよう vol.1 それは何 & Singleton
ODP
curl_multi_exec()でFire-and-forgetに失敗した話
ODP
書こう!正規表現 vol.4 肯定/否定 先読み/戻り読み
ODP
PHPUnit 4.0で追加されたwillReturn*()の紹介
ODP
書こう!正規表現 vol.3 ()
ODP
sedで複数行処理 使ってみようNを
ODP
ctagsでvimにひきこもる
ODP
書こう!正規表現 vol.2 文字クラス(例外)
ODP
書こう!正規表現 vol.2 文字クラス(基本)
ODP
書こう!ユニットテスト vol.2 どうやって?
ODP
書こう!正規表現 vol.1 正規表現 is 何
ODP
書こう!ユニットテスト vol.1 ナンデ?
ODP
PHP foreachでの参照渡しに潜む罠
ODP
Cocproxy
プログラミング言語のマスコットとか紹介
金曜だけどデザインパターンでも勉強しよう
非同期データ更新のためにメッセージキューを導入した(い)話
月曜だからデザインパターンでも勉強しよう vol.4 Builder
月曜だからデザインパターンでも勉強しよう vol.3 Factory Method & Abstract Factory
月曜だからデザインパターンでも勉強しよう vol.2 Flyweight
月曜だからデザインパターンでも勉強しよう vol.1 それは何 & Singleton
curl_multi_exec()でFire-and-forgetに失敗した話
書こう!正規表現 vol.4 肯定/否定 先読み/戻り読み
PHPUnit 4.0で追加されたwillReturn*()の紹介
書こう!正規表現 vol.3 ()
sedで複数行処理 使ってみようNを
ctagsでvimにひきこもる
書こう!正規表現 vol.2 文字クラス(例外)
書こう!正規表現 vol.2 文字クラス(基本)
書こう!ユニットテスト vol.2 どうやって?
書こう!正規表現 vol.1 正規表現 is 何
書こう!ユニットテスト vol.1 ナンデ?
PHP foreachでの参照渡しに潜む罠
Cocproxy

PHP array_uintersectに潜む罠