对于大数组查找某个值in_array和array_flip+isset的性能比较

  •   
  • 6017
  • PHP
  • 10
  • super_dodo
  • 2016/09/21

假设有一个10万条记录的数组,需要查找某一个值是否存在该数组内.大多数情况下直接使用in_array这个PHP的自带函数,但是当这个数组很大和很复杂的时候,建议使用array_flip和isset的方式来提高性能.

首先来看一下PHP源码,从代码中可以看出while循环在遍历数组中的所有元素取值做对比,如果数组中元素特别多又频繁调用的时候,效率可想而知。

由于数组的键是放在Hash表的key中的,Hash遍历会根据键的哈希值去查找,效率非常高,所以尝试了一上array_flip将键值对换,然后用isset去判断,效率呈指数级提高。

//得到毫秒的方法
function getMillisecond() {
list($t1, $t2) = explode(' ', microtime());
return (float)sprintf('%.0f',(floatval($t1)+floatval($t2))*1000);
}

//构建一个10万条自增的新数组
$array = [];
for ($i = 0; $i < 100000; $i++) { $array[] = $i; } //直接使用in_array的方法去循环执行10万次查找 $start_time = getMillisecond(); for ($i = 0; $i < 100000; $i++) { $k = rand(0,100000); if(in_array($k,$array)){ echo $k; } } echo '使用in_array占用时间:', (getMillisecond() - $start_time) . "毫秒


";

//反转键和值array_flip
$start_time = getMillisecond();
$array_flip = array_flip($array);
for ($i = 0; $i < 100000; $i++) { $k = rand(0,100000); if(isset($array_flip[$k])){ echo $k; } } echo '使用isset占用时间:', (getMillisecond() - $start_time) . "毫秒"; //输出结果 //使用in_array占用时间:6336毫秒 //使用isset占用时间:121毫秒 //使用in_array占用时间:6347毫秒 //使用isset占用时间:362毫秒 //使用in_array占用时间:6374毫秒 //使用isset占用时间:161毫秒 //对于10万条数据执行10万次的效率来说,结果令人吃惊,所以建议在做统计等密集运算的时候,尽量不要使用in_array函数! [/php] 附上PHP的in_array的源码,来源于网络,经供参考. [php] /* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) * 0 = return boolean * 1 = return key */ static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */ { zval *value, /* value to check for */ *array, /* array to check in */ **entry, /* pointer to array entry */ res; /* comparison result */ HashPosition pos; /* hash iterator */ zend_bool strict = 0; /* strict comparison or not */ int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) { return; } if (strict) { is_equal_func = is_identical_function; } zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) { is_equal_func(&res, value, *entry TSRMLS_CC); if (Z_LVAL(res)) { if (behavior == 0) { RETURN_TRUE; } else { zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(array), return_value, &pos); return; } } zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos); } RETURN_FALSE; } /* }}} */ [/php]