14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【PHP】『任意の値が配列の要素に含まれているか』を調べる一番いい方法が知りたい

Last updated at Posted at 2016-11-16

■はじめに

動作は5.6と7.0で確認
以下の結果は7.0(というか https://paiza.io/ )によるもの

■配列をそのままに調べる

▼ array_search

● コード

php
$time_start = microtime(TRUE);
$counter = 0;
$range = range(1, 20000);

foreach ($range as $value) {
	$counter += array_search($value, $range, TRUE) === FALSE ? 0 : 1;
}

$time = microtime(TRUE) - $time_start;
echo "{$time} 秒/{$counter} 回";

● 結果

console
0.90795683860779 秒/20000 回

▼ in_array

● コード

php
$time_start = microtime(TRUE);
$counter = 0;
$range = range(1, 20000);

foreach ($range as $value) {
	$counter += in_array($value, $range, TRUE) === FALSE ? 0 : 1;
}

$time = microtime(TRUE) - $time_start;
echo "{$time} 秒/{$counter} 回";

● 結果

console
0.90810298919678 秒/20000 回

■配列のvalueをkeyに入れ直して調べる

▼ array_flip + isset

● コード

php
$time_start = microtime(TRUE);
$counter = 0;
$range = range(1, 20000);

$flipped = array_flip($range);
foreach ($range as $value) {
	$counter += isset($flipped[$value]) === FALSE ? 0 : 1;
}

$time = microtime(TRUE) - $time_start;
echo "{$time} 秒/{$counter} 回";

● 結果

console
0.0013470649719238 秒/20000 回

▼ array_fill_keys + isset

● コード

php
$time_start = microtime(TRUE);
$counter = 0;
$range = range(1, 20000);

$filled = array_fill_keys($range, 0);
foreach ($range as $value) {
	$counter += isset($filled[$value]) === FALSE ? 0 : 1;
}

$time = microtime(TRUE) - $time_start;
echo "{$time} 秒/{$counter} 回";

● 結果

console
0.0015709400177002 秒/20000 回

▼ array_flip + array_key_exists

● コード

php
$time_start = microtime(TRUE);
$counter = 0;
$range = range(1, 20000);

$flipped = array_flip($range);
foreach ($range as $value) {
	$counter += array_key_exists($value, $flipped) === FALSE ? 0 : 1;
}

$time = microtime(TRUE) - $time_start;
echo "{$time} 秒/{$counter} 回";

● 結果

console
0.0017008781433105 秒/20000 回

▼ array_fill_keys + array_key_exists

● コード

php
$time_start = microtime(TRUE);
$counter = 0;
$range = range(1, 20000);

$filled = array_fill_keys($range, 0);
foreach ($range as $value) {
	$counter += array_key_exists($value, $filled) === FALSE ? 0 : 1;
}

$time = microtime(TRUE) - $time_start;
echo "{$time} 秒/{$counter} 回";

● 結果

console
0.0017199516296387 秒/20000 回

▼ そのほか

・配列のvalueをkeyに入れ直すとき、渡す配列のvalueに存在する重複は勝手に除かれる
・配列のvalueをkeyに入れ直すとき、渡す配列のvalueにString・Integer以外の型が存在する場合はエラーまたは型変換される
(渡す配列のvalueに配列が含まれている場合は、目的に拠って配列の平坦化ないしある次元のみを切り出す処理を考えなきゃいけなくなる)

■まとめ

方法 実行時間
array_search 0.9秒
in_array 0.9秒
array_flip + isset 0.0秒
array_fill_keys + isset 0.0秒
array_flip + array_key_exists 0.0秒
array_fill_keys + array_key_exists 0.0秒
※今回は簡易的なベンチマークなので有効桁数を絞ってます

▼ 関数について

関数名(言語構造) 比較の厳密さ 備考
array_search 緩やかな比較(ただし第三引数がTRUEのとき厳密な比較) 戻り値は配列のキーまたはFALSE
in_array 緩やかな比較(ただし第三引数がTRUEのとき厳密な比較) 戻り値はboolean
array_flip --- 渡す配列のvalueが、String型・Integer型以外の値のとき、エラーが出力される(NULLもエラー)
array_fill_keys --- 渡す配列のvalueが、String型・Integer型以外の値のとき、String型に型変換しようとする(できないときはエラー、NULLは空文字に型変換)
isset 緩やかな比較 NULL値を持つ配列キーに対してFALSEを返す
array_key_exists 緩やかな比較 NULL値を持つ配列キーに対してTRUEを返す
※可能ならばDBに対してSELECTした戻り値を確認したほうがいいのかもしれない

■リンク

・比較の厳密さについて
http://php.net/manual/ja/types.comparisons.php
・array_search
http://php.net/manual/ja/function.array-search.php
・in_array
http://php.net/manual/ja/function.in-array.php
・array_flip
http://php.net/manual/ja/function.array-flip.php
・array_fill_keys
http://php.net/manual/ja/function.array-fill-keys.php
・isset
http://php.net/manual/ja/function.isset.php
・array_key_exists
http://php.net/manual/ja/function.array-key-exists.php

一番いい方法を知っていたら教えてくださいorz

14
12
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?