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