您的位置:首页 > PHP > PHP源码阅读笔记十八:array_diff_key,array_diff_assoc,array_udiff_assoc 函数

PHP源码阅读笔记十八:array_diff_key,array_diff_assoc,array_udiff_assoc 函数

PHP源码阅读笔记十八:array_diff_key,array_diff_assoc,array_udiff_assoc
【array_diff_key】

(PHP 5 >= 5.1.0RC1)
array_diff_key — 使用键名比较计算数组的差集
说明

array array_diff_key ( array array1, array array2 [, array ...] )

array_diff_key() 返回一个数组,该数组包括了所有出现在 array1 中但是未出现在任何其它参数数组中的键名的值。注意关联关系保留不变。

【array_diff_assoc】

(PHP 4 >= 4.3.0, PHP 5)
array_diff_assoc — 带索引检查计算数组的差集
说明

array array_diff_assoc ( array array1, array array2 [, array ...] )

array_diff_assoc() 返回一个数组,该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。注意和 array_diff() 不同的是键名也用于比较。

之所以把这三个函数放在一起是因为他们调用的最后是一个函数:php_array_diff_key
【array_diff_uassoc】

(PHP 5)
array_diff_uassoc — 用用户提供的回调函数做索引检查来计算数组的差集
说明

array array_diff_uassoc ( array array1, array array2 [, array ..., callback key_compare_func] )

array_diff_uassoc() 返回一个数组,该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。

这三个函数调用php-array_diff_key的方式如下:

1
2
3
array_diff_key:         php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_NONE);
array_diff_assoc:      php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_INTERNAL);
array_udiff_assoc:    php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_USER);

其中参数的宏定义如下:

1
2
3
4
5
#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC
 
#define DIFF_COMP_DATA_NONE    -1
#define DIFF_COMP_DATA_INTERNAL 0
#define DIFF_COMP_DATA_USER     1

php_array_diff_key函数首先要根据传入的data_compare_type(即上面定义的三个宏),判断所要使用的比较函数,然后遍历第一个数组,针对每一个元素与其它数组比较,看其它数字是否存在
如果存在则删
针对此函数的源码做一个注释性的说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
    for (i = 0; i < argc; i++) {
        if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1);
            RETVAL_NULL();
            goto out;    //    goto语句,这个貌似一般是高手用的,嘿嘿
        }
    }
 
    array_init(return_value);    //    返回数组初始化,初始化存储此数组的Hash Table
 
    for (p = Z_ARRVAL_PP(args[0])->pListHead; p != NULL; p = p->pListNext) {    //    遍历第一个参数包含的双向链表
        if (p->nKeyLength == 0) {    //    数组索引为数字
            ok = 1;
            for (i = 1; i < argc; i++) {    //    对其它的数组进行判断
                if (zend_hash_index_find(Z_ARRVAL_PP(args[i]), p->h, (void**)&data) == SUCCESS &&
                    (!diff_data_compare_func ||
                     diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0)) {
                    ok = 0;
                    break;
                }
            }
            if (ok) {    在第一个数组中,不在其它数组中
                (*((zval**)p->pData))->refcount++;
                zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, p->pData, sizeof(zval*), NULL);
            }
        } else {    //    索引为字符串
            ok = 1;
            for (i = 1; i < argc; i++) {
                if (zend_hash_quick_find(Z_ARRVAL_PP(args[i]), p->arKey, p->nKeyLength, p->h, (void**)&data) == SUCCESS &&
                    (!diff_data_compare_func ||
                     diff_data_compare_func((zval**)p->pData, data TSRMLS_CC) == 0)) {
                    ok = 0;
                    break;
                }
            }
            if (ok) {
                (*((zval**)p->pData))->refcount++;
                zend_hash_quick_update(Z_ARRVAL_P(return_value), p->arKey, p->nKeyLength, p->h, p->pData, sizeof(zval*), NULL);
            }
        }
    }

关于比较函数:
DIFF_COMP_DATA_NONE参数对应的是NULL,即不存在比较,使用索引查找就可以了
DIFF_COMP_DATA_INTERNAL参数对应的是zval_compare,即索引和值都会比较
DIFF_COMP_DATA_USER参数对应的是zval_user_compare,即用户自定义的函数

EOF

本文地址:PHP源码阅读笔记十八:array_diff_key,array_diff_assoc,array_udiff_assoc 函数    文章出处:PHP源码阅读,PHP设计模式,PHP学习笔记,项目管理-胖胖的空间

转载请以链接形式注明原始出处和作者,谢绝不尊重版权者抄袭!

暂无留言我要留言

必填

必填,绝不公开

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word