慎用php的array_search函数

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架构师

转载于:https://my.oschina.net/u/222608/blog/1925786

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值