当前位置: 首页 > news >正文

php array_diff 比较两个数组bug避坑 深入了解

今天实用array_diff出现的异常问题,预想的结果应该是返回 "integral_initiate"=>"0",实际没有

先看测试代码:

$a = ["user_name"=>"测","see_num"=>0,"integral_initiate"=>"0"
];
$b = ["user_name"=>"测","see_num"=>0,"integral_initiate"=>10
];
$gf = array_diff($a,$b);
print_r($gf);

没有返回差异,纠结了好一阵子又查阅了文档看到这一句话才醒悟 

我们简化一下数组来看,通过简化数组发现只要两个数组中间都带有0的值就不会正常效验

解决方案就是换成 array_diff_assoc 对比键名与键值

------------序言--------------

虽然上面得到了想要的结果,但是本着刨根问底的思想继续研究了 一番,查了一些资料,也翻了下源码终于找到了一个合理的解释

/* {{{ proto array array_diff(array arr1, array arr2 [, array ...])Returns the entries of arr1 that have values which are not present in any of the others arguments. */
PHP_FUNCTION(array_diff)
{zval *args;int argc, i;uint32_t num;HashTable exclude;zval *value;zend_string *str, *tmp_str, *key;zend_long idx;zval dummy;if (ZEND_NUM_ARGS() < 2) {php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());return;}ZEND_PARSE_PARAMETERS_START(1, -1)Z_PARAM_VARIADIC('+', args, argc)ZEND_PARSE_PARAMETERS_END();if (Z_TYPE(args[0]) != IS_ARRAY) {php_error_docref(NULL, E_WARNING, "Expected parameter 1 to be an array, %s given", zend_zval_type_name(&args[0]));RETURN_NULL();}num = zend_hash_num_elements(Z_ARRVAL(args[0]));if (num == 0) {for (i = 1; i < argc; i++) {if (Z_TYPE(args[i]) != IS_ARRAY) {php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));RETURN_NULL();}}RETURN_EMPTY_ARRAY();} else if (num == 1) {int found = 0;zend_string *search_str, *tmp_search_str;value = NULL;ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[0]), value) {break;} ZEND_HASH_FOREACH_END();if (!value) {for (i = 1; i < argc; i++) {if (Z_TYPE(args[i]) != IS_ARRAY) {php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));RETURN_NULL();}}RETURN_EMPTY_ARRAY();}search_str = zval_get_tmp_string(value, &tmp_search_str);for (i = 1; i < argc; i++) {if (Z_TYPE(args[i]) != IS_ARRAY) {php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));RETURN_NULL();}if (!found) {ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) {str = zval_get_tmp_string(value, &tmp_str);if (zend_string_equals(search_str, str)) {zend_tmp_string_release(tmp_str);found = 1;break;}zend_tmp_string_release(tmp_str);} ZEND_HASH_FOREACH_END();}}zend_tmp_string_release(tmp_search_str);if (found) {RETVAL_EMPTY_ARRAY();} else {ZVAL_COPY(return_value, &args[0]);}return;}/* count number of elements */num = 0;for (i = 1; i < argc; i++) {if (Z_TYPE(args[i]) != IS_ARRAY) {php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));RETURN_NULL();}num += zend_hash_num_elements(Z_ARRVAL(args[i]));}if (num == 0) {ZVAL_COPY(return_value, &args[0]);return;}ZVAL_NULL(&dummy);/* create exclude map */zend_hash_init(&exclude, num, NULL, NULL, 0);for (i = 1; i < argc; i++) {ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) {str = zval_get_tmp_string(value, &tmp_str);zend_hash_add(&exclude, str, &dummy);zend_tmp_string_release(tmp_str);} ZEND_HASH_FOREACH_END();}/* copy all elements of first array that are not in exclude set */array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(args[0]), idx, key, value) {str = zval_get_tmp_string(value, &tmp_str);if (!zend_hash_exists(&exclude, str)) {if (key) {value = zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);} else {value = zend_hash_index_add_new(Z_ARRVAL_P(return_value), idx, value);}zval_add_ref(value);}zend_tmp_string_release(tmp_str);} ZEND_HASH_FOREACH_END();zend_hash_destroy(&exclude);
}
/* }}} */

这就可以解释为什么使用array_diff 不能得到想要的结果,因为只要第一个数组中的值在第二个数组中出现过就不算差异,所以并不是bug,反过来再去看一下文档上面英文注释是这样写的

我只能说这个中文版的翻译有待提升,至此问题就到这里了

相关文档:

1、问题解答: https://stackoverflow.com/questions/4742405/array-diff-to-compare-two-associative-arrays/4742438#4742438 2、PHP 如何查看php函数源码-CSDN博客

3、源码地址 :GitCode - 开发者的代码家园 

http://www.lryc.cn/news/285758.html

相关文章:

  • c++中STL的vector简单实现
  • C# 更改Bitmap图像色彩模式
  • 5.2 基于深度学习和先验状态的实时指纹室内定位
  • AIGC时代高效阅读论文实操
  • 对网站进行打点(不要有主动扫描行为)
  • 502. IPO(贪心算法+优先队列/堆)
  • 设计模式篇---中介者模式
  • 双端Diff算法
  • react+antd,Table表头文字颜色设置
  • 2024年1月18日Arxiv最热NLP大模型论文:Large Language Models Are Neurosymbolic Reasoners
  • 服务限流实现方案
  • 【RTOS】快速体验FreeRTOS所有常用API(1)工程创建
  • Red Hat Enterprise Linux 8.9 安装图解
  • vcruntime140.dll文件修复的几种常见解决办法,vcruntime140.dll丢失的原因
  • SpringCloud Alibaba 深入源码 - Nacos 分级存储模型、支撑百万服务注册压力、解决并发读写问题(CopyOnWrite)
  • 算法训练营Day45
  • 【Redis漏洞利用总结】
  • SPI 动态服务发现机制
  • 【C++进阶07】哈希表and哈希桶
  • Go 语言实现冒泡排序算法的简单示例
  • JAVA 学习 面试(五)IO篇
  • vue3相比vue2的效率提升
  • web terminal - 如何在mac os上运行gotty
  • 机械设计-哈工大课程学习-螺纹连接
  • ai绘画|stable diffusion的发展史!简短易懂!!!
  • 水塘抽样算法
  • easyui渲染隐藏域<input type=“hidden“ />为textbox可作为分割条使用
  • 100天精通Python(实用脚本篇)——第113天:基于Tesseract-OCR实现OCR图片文字识别实战
  • Go七天实现RPC
  • Elasticsearch:和 LIamaIndex 的集成