世界杯以来,可用分输了不少,爆冷的时候,我稳了,我想爆冷,南非那稳住了,心情极度郁闷,散个200分,希望能让我输到世界杯结束上周做的一个测试,现在匆匆忙忙加了几行注释,发出来,因为皮厚,又戴着深度眼镜,也就不怕贻笑大方了有蛮长一段时间,我都用foreach,in_array,array_search来查找数组中的元素,直觉觉得,系统提供的,都是及其优化后的方案,一直到之前遇到了一些问题。深刻体会到具体问题具体分析的概念下面用了几种常用的判断方法,来检测数组中是否含有某一个元素,过程不说了,有兴趣的一看便知。路过的朋友,若愿意测试,请把测试结果贴上来也希望路过的朋友提供更优的方案,贴在下面,不胜感激set_time_limit(0);$arr = array();//测试数组$arrLength = 5000;//测试数组长度$arrType = 2;//1是1—1亿随机数字,2是8位字符串,3是32位字符串$cycleTimes = 100;//测试次数,尽量避免偶然情况$searchTimes = 50;//查找次数实际是50*2,50个能找到,50个找不到$keywordArr = array();//要比对的元素,数组形式保存$resultArr = array();//记录测试结果的数组/**
* 构造数组元素
*
* @access public
* @param integer $arrType 元素类型
* @param bool $flag 为了构造差异元素
* @return string
*/
function creatItem($arrType = 1, $flag = true)
{
$item = '';
$seed = $flag ? rand(1, 50000000) : rand(50000001, 100000000);
switch($arrType)
{
case 1:
$item = $seed;
break;
case 2:
$item = sprintf('%X', crc32($seed));
break;
default:
$item = md5($seed);
}
return $item;
}//测试数组赋值,同时保存$searchTimes个能找到的元素
for($i=0;$i<$arrLength;$i++)
{
$arr[] = creatItem($arrType, true);
if($i < $searchTimes)
{
$keywordArr[] = $arr[$i];
}
}//构造$searchTimes个测试数组中没有的值
for($i=0;$i<$searchTimes;$i++)
{
$keywordArr[] = creatItem($arrType, false);
}/*********************初始化结束*****************///每种方法测,都用到shuffle,所以这里顺便测试一下效率
$timeStart = gettimeofday();
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
}
$resultArr['shuffle'] = gettimeofday();//开始循环测试foreach
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
foreach($keywordArr AS $v)
{
foreach($arr AS $value)
{
if($value == $v)
{
break;
}
}
}
}
$resultArr['foreach'] = gettimeofday();//开始循环测试in_array
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
foreach($keywordArr AS $v)
{
in_array($v, $arr);
}
}
$resultArr['in_array'] = gettimeofday();//开始循环测试array_search
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
foreach($keywordArr AS $v)
{
array_search($v, $arr);
}
}
$resultArr['array_search'] = gettimeofday();//开始循环测试strpos
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
$arraystring = ',' . implode(',', $arr) . ',';
foreach($keywordArr AS $v)
{
strpos($arraystring, ',' . $v . ',');
}
}
$resultArr['strpos'] = gettimeofday();//开始循环测试array_key_exists
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
$arr = array_flip($arr);
foreach($keywordArr AS $v)
{
array_key_exists($v, $arr);
}
}
$resultArr['array_key_exists'] = gettimeofday();//开始循环测试isset($arr[$key])
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
$arr = array_flip($arr);
foreach($keywordArr AS $v)
{
isset($arr[$v]);
}
}
$resultArr['isset_key'] = gettimeofday();//打印结果
echo var_dump($arrLength, $arrType, $cycleTimes, $searchTimes) . '<br />';
foreach($resultArr AS $k => $v)
{
$time = ($v["usec"]-$timeStart["usec"])/1000000+$v["sec"]-$timeStart["sec"];
$time = round($time, 6)."秒";
echo $time . ' ' . $k . '<br />';
$timeStart = $v;
}
* 构造数组元素
*
* @access public
* @param integer $arrType 元素类型
* @param bool $flag 为了构造差异元素
* @return string
*/
function creatItem($arrType = 1, $flag = true)
{
$item = '';
$seed = $flag ? rand(1, 50000000) : rand(50000001, 100000000);
switch($arrType)
{
case 1:
$item = $seed;
break;
case 2:
$item = sprintf('%X', crc32($seed));
break;
default:
$item = md5($seed);
}
return $item;
}//测试数组赋值,同时保存$searchTimes个能找到的元素
for($i=0;$i<$arrLength;$i++)
{
$arr[] = creatItem($arrType, true);
if($i < $searchTimes)
{
$keywordArr[] = $arr[$i];
}
}//构造$searchTimes个测试数组中没有的值
for($i=0;$i<$searchTimes;$i++)
{
$keywordArr[] = creatItem($arrType, false);
}/*********************初始化结束*****************///每种方法测,都用到shuffle,所以这里顺便测试一下效率
$timeStart = gettimeofday();
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
}
$resultArr['shuffle'] = gettimeofday();//开始循环测试foreach
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
foreach($keywordArr AS $v)
{
foreach($arr AS $value)
{
if($value == $v)
{
break;
}
}
}
}
$resultArr['foreach'] = gettimeofday();//开始循环测试in_array
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
foreach($keywordArr AS $v)
{
in_array($v, $arr);
}
}
$resultArr['in_array'] = gettimeofday();//开始循环测试array_search
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
foreach($keywordArr AS $v)
{
array_search($v, $arr);
}
}
$resultArr['array_search'] = gettimeofday();//开始循环测试strpos
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
$arraystring = ',' . implode(',', $arr) . ',';
foreach($keywordArr AS $v)
{
strpos($arraystring, ',' . $v . ',');
}
}
$resultArr['strpos'] = gettimeofday();//开始循环测试array_key_exists
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
$arr = array_flip($arr);
foreach($keywordArr AS $v)
{
array_key_exists($v, $arr);
}
}
$resultArr['array_key_exists'] = gettimeofday();//开始循环测试isset($arr[$key])
for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
$arr = array_flip($arr);
foreach($keywordArr AS $v)
{
isset($arr[$v]);
}
}
$resultArr['isset_key'] = gettimeofday();//打印结果
echo var_dump($arrLength, $arrType, $cycleTimes, $searchTimes) . '<br />';
foreach($resultArr AS $k => $v)
{
$time = ($v["usec"]-$timeStart["usec"])/1000000+$v["sec"]-$timeStart["sec"];
$time = round($time, 6)."秒";
echo $time . ' ' . $k . '<br />';
$timeStart = $v;
}
我贴的后面两种,是将元素key value交换,并判断key是否存在,,,当然因为效率测下来,两种还是有一点点差异的,所以凑数,就分为了2种你说的键查找,能否详细说?
一份是key=>value,一份是value=>key, 这样查找就很快了.
搜索值是很慢的,但是搜索键很快,因为数组都是hash表,
0,1,2,3等下标直接截断作为hash中的下标,
字符串下标是用time33算法映射到整数下标的.
我的需求,只需判定是否存在,所以数组恢复这个就省了,因为有个array_flip,当比对次数很少的时候,还是不要用的好
如果是我,碰到大数组的情况,一般会考虑牺牲空间,在$arr生成的时候构建一个索引表。其实和array_flip一样。
...
//测试数组赋值,同时保存$searchTimes个能找到的元素
for($i=0;$i<$arrLength;$i++)
{
$arr[$i] = $rvalue = creatItem($arrType, true);
$hash[$rvalue][] = $i;//...
if($i < $searchTimes)
{
$keywordArr[] = $arr[$i];
}
}
..for($i=0;$i<$cycleTimes;$i++)
{
shuffle($arr);
foreach($keywordArr AS $v) isset($hash[$v]);
}
$resultArr['hash'] = gettimeofday();
0.041007秒 shuffle
11.698075秒 foreach
8.002122秒 in_array
7.986511秒 array_search
2.050716秒 strpos
0.237464秒 array_key_exists
0.22903秒 isset_key
还不如直接array_search或者in_array好,
如果判断值是否存在的操作很多,修改的操作不多,
那么维护一个value=>key的数组是很有必要的
接受大部分意见,代码是有点问题不过,有一点异议是,我这里之所以每次循环倒置key,value,是因为完成外层循环测试N次的目的事实上,每一种查找,都加了外层循环N次,以便排除偶然情况,得到较为客观的结果
array_search()这两个方法的。有时会使用 foreach
int(5000) int(2) int(100) int(50)
0.132363秒 shuffle
23.241035秒 foreach
12.559198秒 in_array
12.540035秒 array_search
2.459958秒 strpos
0.393134秒 array_key_exists
0.396289秒 isset_key