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