php array_diff 比较两个数组bug避坑 深入了解
admin 阅读: 2024-03-16
后台-插件-广告管理-内容页头部广告(手机) |
今天实用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 - 开发者的代码家园
声明
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。
在线投稿:投稿 站长QQ:1888636
后台-插件-广告管理-内容页尾部广告(手机) |