array_search是phper使用频次非常高的一个数组函数,但是array_search也是经常被滥用的一个函数,比如假设下面这种业务场景,需要把两个大数组内相同的元素统计出来(恩,没错有个array_intersect函数可以完成这个工作,但这并不妨碍我们讲这个例子)。
如果使用array_search就是这种写法
$arr1 = ['假设他有100万个元素'];
$arr2 = ['假设他有100万个元素'];
$arr3 = [];
foreach ($arr1 as $v) {
$k = array_search($v, $arr2);
if ($k === false) {
$arr3[] = $v;
}
}
array_search的实现,php源码ext/standard/array.c,截取部分代码,宏的实现就不贴出来了,看名字也能猜出来它怎么实现的,就是循环遍历。
static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */
{
if (strict) {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
……
} ZEND_HASH_FOREACH_END();
} else {
if (Z_TYPE_P(value) == IS_LONG) {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
……
} ZEND_HASH_FOREACH_END();
} else if (Z_TYPE_P(value) == IS_STRING) {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
……
} ZEND_HASH_FOREACH_END();
} else {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
……
} ZEND_HASH_FOREACH_END();
}
}
RETURN_FALSE;
}
所以上面这种实现的时间复杂度O(n²),这个时间复杂度是相当恐怖的。
然后,我们看下另外一种实现,把arr2的key和value转换下,由于hashmap的时间复杂度是O(1) ~ O(n)(大多数时候都是1),所以这个实现的时间复杂度O(n),有了质的提升,时间复杂度由二次时间变成了线性时间。
$arr1 = ['假设他有100万个元素'];
$arr2 = array_flip(['假设他有100万个元素']);
$arr3 = [];
foreach ($arr1 as $v) {
if (isset($arr2[$v])) {
$arr3[] = $v;
}
}
我们在做数据统计的时候,经常需要遇到类似的业务场景,能极大的提高程序的运行性能,但是这种写法也有它的局限性,比如value有重复的数据,所以没有万能银弹。
更多架构、PHP、GO相关踩坑实践技巧请关注我的公众号:PHP架构师