您现在的位置是:首页 > 技术教程 正文

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

admin 阅读: 2024-03-16
后台-插件-广告管理-内容页头部广告(手机)

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

先看测试代码:

  1. $a = [
  2. "user_name"=>"测","see_num"=>0,"integral_initiate"=>"0"
  3. ];
  4. $b = [
  5. "user_name"=>"测","see_num"=>0,"integral_initiate"=>10
  6. ];
  7. $gf = array_diff($a,$b);
  8. print_r($gf);

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

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

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

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

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

  1. /* {{{ proto array array_diff(array arr1, array arr2 [, array ...])
  2. Returns the entries of arr1 that have values which are not present in any of the others arguments. */
  3. PHP_FUNCTION(array_diff)
  4. {
  5. zval *args;
  6. int argc, i;
  7. uint32_t num;
  8. HashTable exclude;
  9. zval *value;
  10. zend_string *str, *tmp_str, *key;
  11. zend_long idx;
  12. zval dummy;
  13. if (ZEND_NUM_ARGS() < 2) {
  14. php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
  15. return;
  16. }
  17. ZEND_PARSE_PARAMETERS_START(1, -1)
  18. Z_PARAM_VARIADIC('+', args, argc)
  19. ZEND_PARSE_PARAMETERS_END();
  20. if (Z_TYPE(args[0]) != IS_ARRAY) {
  21. php_error_docref(NULL, E_WARNING, "Expected parameter 1 to be an array, %s given", zend_zval_type_name(&args[0]));
  22. RETURN_NULL();
  23. }
  24. num = zend_hash_num_elements(Z_ARRVAL(args[0]));
  25. if (num == 0) {
  26. for (i = 1; i < argc; i++) {
  27. if (Z_TYPE(args[i]) != IS_ARRAY) {
  28. php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
  29. RETURN_NULL();
  30. }
  31. }
  32. RETURN_EMPTY_ARRAY();
  33. } else if (num == 1) {
  34. int found = 0;
  35. zend_string *search_str, *tmp_search_str;
  36. value = NULL;
  37. ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[0]), value) {
  38. break;
  39. } ZEND_HASH_FOREACH_END();
  40. if (!value) {
  41. for (i = 1; i < argc; i++) {
  42. if (Z_TYPE(args[i]) != IS_ARRAY) {
  43. php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
  44. RETURN_NULL();
  45. }
  46. }
  47. RETURN_EMPTY_ARRAY();
  48. }
  49. search_str = zval_get_tmp_string(value, &tmp_search_str);
  50. for (i = 1; i < argc; i++) {
  51. if (Z_TYPE(args[i]) != IS_ARRAY) {
  52. php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
  53. RETURN_NULL();
  54. }
  55. if (!found) {
  56. ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) {
  57. str = zval_get_tmp_string(value, &tmp_str);
  58. if (zend_string_equals(search_str, str)) {
  59. zend_tmp_string_release(tmp_str);
  60. found = 1;
  61. break;
  62. }
  63. zend_tmp_string_release(tmp_str);
  64. } ZEND_HASH_FOREACH_END();
  65. }
  66. }
  67. zend_tmp_string_release(tmp_search_str);
  68. if (found) {
  69. RETVAL_EMPTY_ARRAY();
  70. } else {
  71. ZVAL_COPY(return_value, &args[0]);
  72. }
  73. return;
  74. }
  75. /* count number of elements */
  76. num = 0;
  77. for (i = 1; i < argc; i++) {
  78. if (Z_TYPE(args[i]) != IS_ARRAY) {
  79. php_error_docref(NULL, E_WARNING, "Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
  80. RETURN_NULL();
  81. }
  82. num += zend_hash_num_elements(Z_ARRVAL(args[i]));
  83. }
  84. if (num == 0) {
  85. ZVAL_COPY(return_value, &args[0]);
  86. return;
  87. }
  88. ZVAL_NULL(&dummy);
  89. /* create exclude map */
  90. zend_hash_init(&exclude, num, NULL, NULL, 0);
  91. for (i = 1; i < argc; i++) {
  92. ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) {
  93. str = zval_get_tmp_string(value, &tmp_str);
  94. zend_hash_add(&exclude, str, &dummy);
  95. zend_tmp_string_release(tmp_str);
  96. } ZEND_HASH_FOREACH_END();
  97. }
  98. /* copy all elements of first array that are not in exclude set */
  99. array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));
  100. ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(args[0]), idx, key, value) {
  101. str = zval_get_tmp_string(value, &tmp_str);
  102. if (!zend_hash_exists(&exclude, str)) {
  103. if (key) {
  104. value = zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
  105. } else {
  106. value = zend_hash_index_add_new(Z_ARRVAL_P(return_value), idx, value);
  107. }
  108. zval_add_ref(value);
  109. }
  110. zend_tmp_string_release(tmp_str);
  111. } ZEND_HASH_FOREACH_END();
  112. zend_hash_destroy(&exclude);
  113. }
  114. /* }}} */

这就可以解释为什么使用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

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索
排行榜