Hi, the attached unified diffs can be used to add new function named array_diff_assoc(). This function works like array_diff() (and shares most of it code) but it is more restrictive. An element from the result array is removed if there is an element in arrays from 2 to N that has same value and same key. PHP script for testing is also attached.
Regards, Andrey P.S. Note that basic_functions.c in the CVS is newer than mine.
--- ../../../php4-200209030900/ext/standard/array.c Sat Aug 24 04:35:58 2002 +++ array.c Wed Sep 4 00:38:16 2002 @@ -2588,9 +2588,7 @@ } /* }}} */ -/* {{{ 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) +static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior TSRMLS_DC ) { zval ***args = NULL; HashTable *hash; @@ -2614,20 +2612,23 @@ set_compare_func(SORT_STRING TSRMLS_CC); 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); + php_error(E_WARNING, "Argument #%d to array_diff() is not an array", i+1); argc = i; /* only free up to i-1 */ goto out; } hash = HASH_OF(*args[i]); list = (Bucket **) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket *), hash->persistent); if (!list) - RETURN_FALSE; + RETURN_FALSE; lists[i] = list; ptrs[i] = list; for (p = hash->pListHead; p; p = p->pListNext) - *list++ = p; + *list++ = p; *list = NULL; - zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), array_data_compare TSRMLS_CC); + if (behavior == 1) + zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), array_key_compare TSRMLS_CC); + else + zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), array_data_compare TSRMLS_CC); } /* copy the argument array */ @@ -2635,16 +2636,29 @@ zval_copy_ctor(return_value); /* go through the lists and look for values of ptr[0] - that are not in the others */ + that are not in the others */ while (*ptrs[0]) { c = 1; for (i=1; i<argc; i++) { - while (*ptrs[i] && (0 < (c = array_data_compare(ptrs[0], ptrs[i] TSRMLS_CC)))) - ptrs[i]++; - if (!c) { - if (*ptrs[i]) + if (behavior == 0){ + while (*ptrs[i] && (0 < (c = array_data_compare(ptrs[0], ptrs[i] TSRMLS_CC)))) + ptrs[i]++; + }else if (behavior == 1){ + while (*ptrs[i] && (0 < (c = array_key_compare(ptrs[0], ptrs[i] TSRMLS_CC)))) ptrs[i]++; - break; + } + if (!c) { + if (behavior == 0){ + if (*ptrs[i]) + ptrs[i]++; + break; + }else if (behavior == 1){ + if (*ptrs[i]){ + if (array_data_compare(ptrs[0], ptrs[i] TSRMLS_CC) != 0){ + c = -1; + } + } + } } } if (!c) { @@ -2658,8 +2672,13 @@ zend_hash_index_del(Z_ARRVAL_P(return_value), p->h); if (!*++ptrs[0]) goto out; - if (array_data_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC)) - break; + if (behavior == 0){ + if (array_data_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC)) + break; + }else{ + if (array_key_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC)) /* always ==1 */ + break; + } } } else { /* ptrs[0] in none of the other arguments */ @@ -2667,22 +2686,45 @@ for (;;) { if (!*++ptrs[0]) goto out; - if (array_data_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC)) - break; + if (behavior == 0){ + if (array_data_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC)) + break; + }else{ + if (array_key_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC)) /* always ==1 */ + break; + } } } } out: for (i=0; i<argc; i++) { - hash = HASH_OF(*args[i]); + hash = HASH_OF(*args[i]); pefree(lists[i], hash->persistent); } efree(ptrs); efree(lists); efree(args); } + + +/* {{{ 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) +{ + php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0 TSRMLS_CC); +} /* }}} */ + +/* {{{ proto array array_diff_assoc(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_assoc) +{ + php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1 TSRMLS_CC); +} +/* }}} */ + + #define MULTISORT_ORDER 0 #define MULTISORT_TYPE 1 #define MULTISORT_LAST 2 @@ -3420,3 +3462,4 @@ * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ +
--- ../../../php4-200209030900/ext/standard/php_array.h Mon May 13 20:36:10 2002 +++ php_array.h Tue Sep 3 07:31:01 2002 @@ -76,6 +76,7 @@ PHP_FUNCTION(array_unique); PHP_FUNCTION(array_intersect); PHP_FUNCTION(array_diff); +PHP_FUNCTION(array_diff_assoc); PHP_FUNCTION(array_sum); PHP_FUNCTION(array_filter); PHP_FUNCTION(array_map);
--- ../../../php4-200209030900/ext/standard/basic_functions.c Tue Aug 27 02:41:49 2002 +++ basic_functions.c Tue Sep 3 07:30:43 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.499 2002/08/26 23:16:51 helly Exp $ */ +/* $Id: basic_functions.c,v 1.498 2002/08/25 18:21:40 helly Exp $ */ #include "php.h" #include "php_streams.h" @@ -785,6 +785,7 @@ PHP_FE(array_unique, NULL) PHP_FE(array_intersect, NULL) PHP_FE(array_diff, NULL) + PHP_FE(array_diff_assoc, NULL) PHP_FE(array_sum, NULL) PHP_FE(array_filter, NULL) PHP_FE(array_map, NULL) @@ -1435,7 +1436,7 @@ 3 = save to file in 3rd parameter */ -/* {{{ proto bool error_log(string message [, int message_type [, string destination [, string extra_headers]]]) +/* {{{ proto bool error_log(string message, int message_type [, string destination] [, string extra_headers]) Send an error message somewhere */ PHP_FUNCTION(error_log) { @@ -1473,7 +1474,7 @@ case 4: if (zend_get_parameters_ex (4, &string, &erropt, &option, &emailhead) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid arguments"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid arguments in"); RETURN_FALSE; } break;
<?php $a = array(1,"big"=>2,3,6,3,5,3,3,3,3,3,3,3,3,3,3); $b = array(2,2,3,3,3,3,3,3,3,3,3,3,3,3,3); $c = array(-1,1); echo '$a='.var_export($a,TRUE).";\n"; echo '$b='.var_export($b,TRUE).";\n"; echo '$c='.var_export($c,TRUE).";\n"; var_dump(array_diff($a,$b,$c)); var_dump(array_diff_assoc($a,$b,$c)); ?>
-- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php