PHP7源码之array_flip函数分析 (2)

zend_hash_index_update 的三个参数分别是:需要更新的哈希表 Z_ARRVAL_P(return_value),整型下标 Z_LVAL_P(entry),值 &data。
如果str_idx 不为空,就将 str_idx 拷贝给 data ,反之将 num_idx 拷贝给 data ,然后使用 zend_hash_index_update 函数将值插入/更新到返回数组中。

如果数组元素的索引为字符串:

else if (Z_TYPE_P(entry) == IS_STRING) { if (str_idx) { ZVAL_STR_COPY(&data, str_idx); } else { ZVAL_LONG(&data, num_idx); } zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data); }

如果str_idx 不为空,就将 str_idx 拷贝给 data ,反之将 num_idx 拷贝给 data ,然后使用 zend_symtable_update 函数将值插入/更新到返回数组中。

数组元素的值只能为字符串或整数,否则报 warning 错误:

else { php_error_docref(NULL, E_WARNING, "Can only flip STRING and INTEGER values!"); }

以上就是 array_flip 函数的源码分析。(END)

后记:其实一开始的标题是『为什么array_flip(array_flip())比array_unique()快』,于是有了以下的篇幅☟,再然后觉得要追根溯源,于是去研究 PHP7 的源代码,于是标题改成了『PHP7源码解释为什么array_flip(array_flip())比array_unique()快』,就有了上边的篇幅☝,可没想到光一个 array_flip 函数的源码整理就用去了不少时间,遂定为『PHP7源码之array_flip函数』,等后面得了时间再整理 array_unique 函数的笔记。(捂脸)
今天在项目中看到这样一句代码

$userIds = array_flip(array_flip($ids));

显而易见,这是为了去重,因为 array_flip 函数可以交换数组中的键和值,原来重复的值会变为相同的键。再进行一次键值互换,把键和值换回来则可以完成去重。
想起几年前跟朋友学 PHP 时,朋友说去重函数 array_unique 性能不高,要少用。只不过那时是初学,没有刨根问底。可今天不忙,就亲自动手测试了一下,简易代码如下:

//运行开始 $startTime = getMicrotime(); $startMemory = getUseMemory(); $arr = [1,2,3...]; // 数据略 array_unique($arr); // array_flip(array_flip($arr)); //运行结束 $endTime = getMicrotime(); $endMemory = getUseMemory(); //运行结果 echo "执行耗时:" . ($endTime - $startTime) * 1000 . '毫秒'; echo "占用内存:" . ($endMemory - $startMemory) . 'kb'; /** * 获取时间(微秒) */ function getMicrotime(){ list($usec, $sec) = explode(' ', microtime()); return (float)$usec + (float)$sec; } /** * 获取使用内存(kb) */ function getUseMemory(){ $useMemory = round(memory_get_usage(true) / 1024, 2); return $useMemory; }

注:代码在终端执行:CentOS 7.4,PHP 7.3.4。

1w个元素,15个重复元素:

array_unique 0.84280967712402 ms 0.95009803771973 ms 0.85306167602539 ms 0.90694427490234 ms 0.87213516235352 ms
  0 kb   0 kb   0 kb   0 kb   0 kb  
array_flip   0.7328987121582 ms   0.74005126953125 ms   0.76198577880859 ms   0.77080726623535 ms   0.79989433288574 ms  
  0 kb   0 kb   0 kb   0 kb   0 kb  

可以看到 array_unique 函数去重确实比 array_flip 函数所用时间长一些,但差异不大。

如果是10w个元素,10个重复元素:

array_unique 15.263795852661 ms 23.360013961792 ms 15.237092971802 ms 15.599012374878 ms 15.784978866577 ms
  0 kb   0 kb   0 kb   0 kb   0 kb  
array_flip   10.167121887207 ms   10.363101959229 ms   10.868072509766 ms   10.629892349243 ms   10.660171508789 ms  
  0 kb   0 kb   0 kb   0 kb   0 kb  

可以看到两个函数的耗时拉开了差距。相信随着数据量的增大,耗时的差距也会更大。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgwjxw.html