Hi all,
I needed to intersect an array with database records indexed by the primary
key, with an array with keys and there is no php function that will do it
internally.
The database array looks like:
$records = array ( 2587 => array('Name', 'Address', 'zip'), ...);
And the array with PKS:
$pks = array_flip(array ( 234, 897, 2587, 6788));
And the intersection would be:
$result = array_intersect_key($records, $pks);
This last action should be done 10.000 times or more, so a pure PHP
implementation takes too long, then I made the following patch to PHP-5.0.0
and PHP-4.3.8 that implements the intersection only comparing the array
keys.
If someone would like to commit it, maybe it would be useful to other users.
Regards,
Cristiano Duarte
***********************Patch for PHP 5.0.0
--- array.c 2004-07-11 18:15:04.000000000 -0300
+++ /home/aluno/php-5.0.0-new/ext/standard/array.c 2004-07-20
13:58:47.000000000 -0300
@@ -84,6 +84,7 @@
#define INTERSECT_NORMAL 0
#define INTERSECT_ASSOC 1
+#define INTERSECT_KEY 2
#define INTERSECT_COMP_DATA_INTERNAL 0
#define INTERSECT_COMP_DATA_USER 1
#define INTERSECT_COMP_KEY_INTERNAL 0
@@ -2797,7 +2798,8 @@
php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d.
This should never happen. Please report as a bug", data_compare_type);
return;
}
-
} else if (behavior == INTERSECT_ASSOC) {
-
} else if ((behavior == INTERSECT_ASSOC)
-
||(behavior == INTERSECT_KEY)) { intersect_key_compare_func = array_key_compare; if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL &&
@@ -2910,7 +2912,7 @@
*list = NULL;
if (behavior == INTERSECT_NORMAL) {
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *),
intersect_data_compare_func TSRMLS_CC);
-
} else if (behavior == INTERSECT_ASSOC) {
-
} else if ((behavior == INTERSECT_ASSOC) || (behavior == INTERSECT_KEY))
{
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *),
intersect_key_compare_func TSRMLS_CC);
}
}
@@ -2926,7 +2928,8 @@
/* go through the lists and look for common values */
while (*ptrs[0]) {
-
if (behavior == INTERSECT_ASSOC
-
if ((behavior == INTERSECT_ASSOC
-
|| behavior == INTERSECT_KEY) && key_compare_type == INTERSECT_COMP_KEY_USER) {
@@ -2938,11 +2941,11 @@
while (*ptrs[i] && (0 < (c = intersect_data_compare_func(ptrs[0],
ptrs[i] TSRMLS_CC)))) {
ptrs[i]++;
}
-
} else if (behavior == INTERSECT_ASSOC) {
-
} else if (behavior == INTERSECT_ASSOC || behavior == INTERSECT_KEY) { while (*ptrs[i] && (0 < (c = intersect_key_compare_func(ptrs[0],
ptrs[i] TSRMLS_CC)))) {
ptrs[i]++;
}
-
if (!c && *ptrs[i]) { /* this means that ptrs[i] is not `NULL` so we can
compare */
-
if ((!c && *ptrs[i]) && (behavior == INTERSECT_ASSOC)) { /* this means
that ptrs[i] is not NULL
so we can compare /
/ and "c==0" is from last operation */
if (data_compare_type == INTERSECT_COMP_DATA_USER) {
BG(user_compare_func_name) = args[arr_argc];
@@ -2996,7 +2999,7 @@
if (0 <= intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)) {
break;
}
-
} else if (behavior == INTERSECT_ASSOC) {
-
} else if (behavior == INTERSECT_ASSOC || behavior == INTERSECT_KEY) { /* no need of looping because indexes are unique */ break; }
@@ -3012,7 +3015,7 @@
if (intersect_data_compare_func(ptrs[0]-1, ptrs[0] TSRMLS_CC)) {
break;
}
-
} else if (behavior == INTERSECT_ASSOC) {
-
} else if (behavior == INTERSECT_ASSOC || behavior == INTERSECT_KEY) { /* no need of looping because indexes are unique */ break; }
@@ -3053,6 +3056,25 @@
/* {{{ proto array array_intersect_assoc(array arr1, array arr2 [,
array ...])
Returns the entries of arr1 that have values which are present in all
the other arguments. Keys are used to do more restrictive check */
+PHP_FUNCTION(array_intersect_key)
+{
-
php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY,
-
INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_INTERNAL);
+}
+/* }}} */
+/* {{{ proto array array_uintersect_assoc(array arr1, array arr2 [,
array ...], callback data_compare_func)
- Returns the entries of arr1 that have values which are present in all
the other arguments. Keys are used to do more restrictive check. Data is
compared by using an user-supplied callback. */
+PHP_FUNCTION(array_uintersect_key)
+{ -
php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY,
-
INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER);
+}
+/* }}} */
+/* {{{ proto array array_intersect_assoc(array arr1, array arr2 [,
array ...])
- Returns the entries of arr1 that have values which are present in all
the other arguments. Keys are used to do more restrictive check */
PHP_FUNCTION(array_intersect_assoc)
{
php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC,
--- basic_functions.c 2004-06-27 18:49:47.000000000 -0300
+++ /home/aluno/php-5.0.0-new/ext/standard/basic_functions.c 2004-07-20
14:15:00.000000000 -0300
@@ -780,6 +780,8 @@
PHP_FE(array_unique, NULL)
PHP_FE(array_intersect, NULL)
PHP_FE(array_uintersect, NULL) -
PHP_FE(array_intersect_key, NULL)
-
PHP_FE(array_uintersect_key, NULL) PHP_FE(array_intersect_assoc, NULL) PHP_FE(array_uintersect_assoc, NULL) PHP_FE(array_intersect_uassoc, NULL)
--- php_array.h 2004-01-08 15:32:51.000000000 -0200
+++ /home/aluno/php-5.0.0-new/ext/standard/php_array.h 2004-07-20
14:15:21.000000000 -0300
@@ -77,6 +77,8 @@
PHP_FUNCTION(array_unique);
PHP_FUNCTION(array_intersect);
PHP_FUNCTION(array_uintersect);
+PHP_FUNCTION(array_intersect_key);
+PHP_FUNCTION(array_uintersect_key);
PHP_FUNCTION(array_intersect_assoc);
PHP_FUNCTION(array_uintersect_assoc);
PHP_FUNCTION(array_intersect_uassoc);
***********************Patch for PHP 4.3.8
--- array.c 2004-04-01 16:07:01.000000000 -0300
+++ /home/aluno/php-4.3.8-new/ext/standard/array.c 2004-07-20
14:06:48.000000000 -0300
@@ -81,6 +81,7 @@
#define INTERSECT_NORMAL 0
#define INTERSECT_ASSOC 1
+#define INTERSECT_KEY 2
PHP_MINIT_FUNCTION(array)
{
@@ -2579,7 +2580,7 @@
*list = NULL;
if (behavior == INTERSECT_NORMAL) {
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *),
array_data_compare TSRMLS_CC);
-
} else if (behavior == INTERSECT_ASSOC) {
-
} else if ((behavior == INTERSECT_ASSOC) || (behavior == INTERSECT_KEY))
{
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *),
array_key_compare TSRMLS_CC);
}
}
@@ -2594,17 +2595,20 @@
if (behavior == INTERSECT_NORMAL) {
while (*ptrs[i] && (0 < (c = array_data_compare(ptrs[0], ptrs[i]
TSRMLS_CC))))
ptrs[i]++;
-
} else if (behavior == INTERSECT_ASSOC) {
-
} else if ((behavior == INTERSECT_ASSOC)
-
|| (behavior == INTERSECT_KEY)) { while (*ptrs[i] && (0 < (c = array_key_compare(ptrs[0], ptrs[i]
TSRMLS_CC))))
ptrs[i]++;
-
if (!c && *ptrs[i]) { /* this means that ptrs[i] is not `NULL` so we can
compare */
-
/* and "c==0" is from last operation */
-
if (array_data_compare(ptrs[0], ptrs[i] TSRMLS_CC) != 0) {
-
c = 1;
-
/* we are going to the break */
-
} else {
-
/* continue looping */
-
}
-
if (behavior == INTERSECT_ASSOC) {
-
if (!c && *ptrs[i]) { /* this means that ptrs[i] is not `NULL` so we can
compare */
-
/* and "c==0" is from last operation */
-
if (array_data_compare(ptrs[0], ptrs[i] TSRMLS_CC) != 0) {
-
c = 1;
-
/* we are going to the break */
-
} else {
-
/* continue looping */
-
}
-
} } } if (!*ptrs[i]) {
@@ -2639,7 +2643,8 @@
if (behavior == INTERSECT_NORMAL) {
if (0 <= array_data_compare(ptrs[0], ptrs[i] TSRMLS_CC))
break;
-
} else if (behavior == INTERSECT_ASSOC) {
-
} else if ((behavior == INTERSECT_ASSOC)
-
|| (behavior == INTERSECT_KEY)) { /* no need of looping because indexes are unique */ break; }
@@ -2653,7 +2658,8 @@
if (behavior == INTERSECT_NORMAL) {
if (array_data_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC))
break;
-
} else if (behavior == INTERSECT_ASSOC) {
-
} else if ((behavior == INTERSECT_ASSOC)
-
|| (behavior == INTERSECT_KEY)) { /* no need of looping because indexes are unique */ break; }
@@ -2688,6 +2694,15 @@
/* }}} */
+/* {{{ proto array array_intersect_key(array arr1, array arr2 [,
array ...])
- Returns the entries of arr1 that have keys which are present in all the
other arguments. */
+PHP_FUNCTION(array_intersect_key)
+{ -
php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU,
INTERSECT_KEY);
+}
+/* }}} */
static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior)
{
zval ***args = NULL;
--- basic_functions.c 2004-05-24 14:02:31.000000000 -0300
+++ /home/aluno/php-4.3.8-new/ext/standard/basic_functions.c 2004-07-20
14:11:50.000000000 -0300
@@ -838,6 +838,7 @@
PHP_FE(array_rand, NULL)
PHP_FE(array_unique, NULL)
PHP_FE(array_intersect, NULL)
-
PHP_FE(array_intersect_key, NULL) PHP_FE(array_intersect_assoc, NULL) PHP_FE(array_diff, NULL) PHP_FE(array_diff_assoc, NULL)
--- php_array.h 2002-12-31 14:35:32.000000000 -0200
+++ /home/aluno/php-4.3.8-new/ext/standard/php_array.h 2004-07-20
14:04:38.000000000 -0300
@@ -75,6 +75,7 @@
PHP_FUNCTION(array_rand);
PHP_FUNCTION(array_unique);
PHP_FUNCTION(array_intersect);
+PHP_FUNCTION(array_intersect_key);
PHP_FUNCTION(array_intersect_assoc);
PHP_FUNCTION(array_diff);
PHP_FUNCTION(array_diff_assoc);
Hello Cristiano,
First, I'd like to say that a function of this type sounds useful.
It's one that I've wanted for some time, particularly for verifying
that an array has the correct keys when it is passed as a function
parameter.
If I understand what you are doing correctly, the same thing can be
accomplished by:
array_intersect(array_keys($records), array(234, 567, 890, 123))
However, I agree that array_diff_key()
and array_intersect_key()
would be significantly useful functions to add to the core.
--
Best regards,
Jason mailto:jason@ionzoft.com
Tuesday, July 20, 2004, 3:16:20 PM, you wrote:
CD> Hi all,
CD> I needed to intersect an array with database records indexed by the primary
CD> key, with an array with keys and there is no php function that will do it
CD> internally.
CD> The database array looks like:
CD> $records = array ( 2587 => array('Name', 'Address', 'zip'), ...);
is "make test" showing problems? (i am just currious).
I will try to review the patch later today (atm i am sick).
andrey
Cristiano Duarte wrote:
Hi all,
I needed to intersect an array with database records indexed by the primary
key, with an array with keys and there is no php function that will do it
internally.
The database array looks like:
$records = array ( 2587 => array('Name', 'Address', 'zip'), ...);And the array with PKS:
$pks = array_flip(array ( 234, 897, 2587, 6788));And the intersection would be:
$result = array_intersect_key($records, $pks);This last action should be done 10.000 times or more, so a pure PHP
implementation takes too long, then I made the following patch to PHP-5.0.0
and PHP-4.3.8 that implements the intersection only comparing the array
keys.If someone would like to commit it, maybe it would be useful to other users.
Regards,
Cristiano Duarte
***********************Patch for PHP 5.0.0
--- array.c 2004-07-11 18:15:04.000000000 -0300
+++ /home/aluno/php-5.0.0-new/ext/standard/array.c 2004-07-20
13:58:47.000000000 -0300
@@ -84,6 +84,7 @@#define INTERSECT_NORMAL 0
#define INTERSECT_ASSOC 1
+#define INTERSECT_KEY 2
#define INTERSECT_COMP_DATA_INTERNAL 0
#define INTERSECT_COMP_DATA_USER 1
#define INTERSECT_COMP_KEY_INTERNAL 0
@@ -2797,7 +2798,8 @@
php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d.
This should never happen. Please report as a bug", data_compare_type);
return;
}
} else if (behavior == INTERSECT_ASSOC) {
} else if ((behavior == INTERSECT_ASSOC)
||(behavior == INTERSECT_KEY)) { intersect_key_compare_func = array_key_compare; if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL &&
@@ -2910,7 +2912,7 @@
*list = NULL;
if (behavior == INTERSECT_NORMAL) {
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *),
intersect_data_compare_func TSRMLS_CC);
} else if (behavior == INTERSECT_ASSOC) {
} else if ((behavior == INTERSECT_ASSOC) || (behavior == INTERSECT_KEY))
{
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *),
intersect_key_compare_func TSRMLS_CC);
}
}
@@ -2926,7 +2928,8 @@/* go through the lists and look for common values */ while (*ptrs[0]) {
if (behavior == INTERSECT_ASSOC
if ((behavior == INTERSECT_ASSOC
|| behavior == INTERSECT_KEY) && key_compare_type == INTERSECT_COMP_KEY_USER) {
@@ -2938,11 +2941,11 @@
while (*ptrs[i] && (0 < (c = intersect_data_compare_func(ptrs[0],
ptrs[i] TSRMLS_CC)))) {
ptrs[i]++;
}
} else if (behavior == INTERSECT_ASSOC) {
} else if (behavior == INTERSECT_ASSOC || behavior == INTERSECT_KEY) { while (*ptrs[i] && (0 < (c = intersect_key_compare_func(ptrs[0],
ptrs[i] TSRMLS_CC)))) {
ptrs[i]++;
}
if (!c && *ptrs[i]) { /* this means that ptrs[i] is not `NULL` so we can
compare */
if ((!c && *ptrs[i]) && (behavior == INTERSECT_ASSOC)) { /* this means
that ptrs[i] is not
NULL
so we can compare /
/ and "c==0" is from last operation */
if (data_compare_type == INTERSECT_COMP_DATA_USER) {
BG(user_compare_func_name) = args[arr_argc];
@@ -2996,7 +2999,7 @@
if (0 <= intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)) {
break;
}
} else if (behavior == INTERSECT_ASSOC) {
} else if (behavior == INTERSECT_ASSOC || behavior == INTERSECT_KEY) { /* no need of looping because indexes are unique */ break; }
@@ -3012,7 +3015,7 @@
if (intersect_data_compare_func(ptrs[0]-1, ptrs[0] TSRMLS_CC)) {
break;
}
} else if (behavior == INTERSECT_ASSOC) {
} else if (behavior == INTERSECT_ASSOC || behavior == INTERSECT_KEY) { /* no need of looping because indexes are unique */ break; }
@@ -3053,6 +3056,25 @@
/* {{{ proto array array_intersect_assoc(array arr1, array arr2 [,
array ...])
Returns the entries of arr1 that have values which are present in all
the other arguments. Keys are used to do more restrictive check */
+PHP_FUNCTION(array_intersect_key)
+{
php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY,
INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_INTERNAL);
+}
+/* }}} */
+/* {{{ proto array array_uintersect_assoc(array arr1, array arr2 [,
array ...], callback data_compare_func)
- Returns the entries of arr1 that have values which are present in all
the other arguments. Keys are used to do more restrictive check. Data is
compared by using an user-supplied callback. */
+PHP_FUNCTION(array_uintersect_key)
+{php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY,
INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER);
+}
+/* }}} */
+/* {{{ proto array array_intersect_assoc(array arr1, array arr2 [,
array ...])
- Returns the entries of arr1 that have values which are present in all
the other arguments. Keys are used to do more restrictive check */
PHP_FUNCTION(array_intersect_assoc)
{
php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC,
--- basic_functions.c 2004-06-27 18:49:47.000000000 -0300
+++ /home/aluno/php-5.0.0-new/ext/standard/basic_functions.c 2004-07-20
14:15:00.000000000 -0300
@@ -780,6 +780,8 @@
PHP_FE(array_unique, NULL)
PHP_FE(array_intersect, NULL)
PHP_FE(array_uintersect, NULL)PHP_FE(array_intersect_key, NULL)
PHP_FE(array_uintersect_key, NULL) PHP_FE(array_intersect_assoc, NULL) PHP_FE(array_uintersect_assoc, NULL) PHP_FE(array_intersect_uassoc, NULL)
--- php_array.h 2004-01-08 15:32:51.000000000 -0200
+++ /home/aluno/php-5.0.0-new/ext/standard/php_array.h 2004-07-20
14:15:21.000000000 -0300
@@ -77,6 +77,8 @@
PHP_FUNCTION(array_unique);
PHP_FUNCTION(array_intersect);
PHP_FUNCTION(array_uintersect);
+PHP_FUNCTION(array_intersect_key);
+PHP_FUNCTION(array_uintersect_key);
PHP_FUNCTION(array_intersect_assoc);
PHP_FUNCTION(array_uintersect_assoc);
PHP_FUNCTION(array_intersect_uassoc);***********************Patch for PHP 4.3.8
--- array.c 2004-04-01 16:07:01.000000000 -0300
+++ /home/aluno/php-4.3.8-new/ext/standard/array.c 2004-07-20
14:06:48.000000000 -0300
@@ -81,6 +81,7 @@#define INTERSECT_NORMAL 0
#define INTERSECT_ASSOC 1
+#define INTERSECT_KEY 2PHP_MINIT_FUNCTION(array)
{
@@ -2579,7 +2580,7 @@
*list = NULL;
if (behavior == INTERSECT_NORMAL) {
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *),
array_data_compare TSRMLS_CC);
} else if (behavior == INTERSECT_ASSOC) {
} else if ((behavior == INTERSECT_ASSOC) || (behavior == INTERSECT_KEY))
{
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *),
array_key_compare TSRMLS_CC);
}
}
@@ -2594,17 +2595,20 @@
if (behavior == INTERSECT_NORMAL) {
while (*ptrs[i] && (0 < (c = array_data_compare(ptrs[0], ptrs[i]
TSRMLS_CC))))
ptrs[i]++;
} else if (behavior == INTERSECT_ASSOC) {
} else if ((behavior == INTERSECT_ASSOC)
|| (behavior == INTERSECT_KEY)) { while (*ptrs[i] && (0 < (c = array_key_compare(ptrs[0], ptrs[i]
TSRMLS_CC))))
ptrs[i]++;
if (!c && *ptrs[i]) { /* this means that ptrs[i] is not `NULL` so we can
compare */
/* and "c==0" is from last operation */
if (array_data_compare(ptrs[0], ptrs[i] TSRMLS_CC) != 0) {
c = 1;
/* we are going to the break */
} else {
/* continue looping */
}
if (behavior == INTERSECT_ASSOC) {
if (!c && *ptrs[i]) { /* this means that ptrs[i] is not `NULL` so we can
compare */
/* and "c==0" is from last operation */
if (array_data_compare(ptrs[0], ptrs[i] TSRMLS_CC) != 0) {
c = 1;
/* we are going to the break */
} else {
/* continue looping */
}
} } } if (!*ptrs[i]) {
@@ -2639,7 +2643,8 @@
if (behavior == INTERSECT_NORMAL) {
if (0 <= array_data_compare(ptrs[0], ptrs[i] TSRMLS_CC))
break;
} else if (behavior == INTERSECT_ASSOC) {
} else if ((behavior == INTERSECT_ASSOC)
|| (behavior == INTERSECT_KEY)) { /* no need of looping because indexes are unique */ break; }
@@ -2653,7 +2658,8 @@
if (behavior == INTERSECT_NORMAL) {
if (array_data_compare(ptrs[0]-1, ptrs[0] TSRMLS_CC))
break;
} else if (behavior == INTERSECT_ASSOC) {
} else if ((behavior == INTERSECT_ASSOC)
|| (behavior == INTERSECT_KEY)) { /* no need of looping because indexes are unique */ break; }
@@ -2688,6 +2694,15 @@
/* }}} */+/* {{{ proto array array_intersect_key(array arr1, array arr2 [,
array ...])
- Returns the entries of arr1 that have keys which are present in all the
other arguments. */
+PHP_FUNCTION(array_intersect_key)
+{php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU,
INTERSECT_KEY);
+}
+/* }}} */
static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior)
{
zval ***args = NULL;
--- basic_functions.c 2004-05-24 14:02:31.000000000 -0300
+++ /home/aluno/php-4.3.8-new/ext/standard/basic_functions.c 2004-07-20
14:11:50.000000000 -0300
@@ -838,6 +838,7 @@
PHP_FE(array_rand, NULL)
PHP_FE(array_unique, NULL)
PHP_FE(array_intersect, NULL)
PHP_FE(array_intersect_key, NULL) PHP_FE(array_intersect_assoc, NULL) PHP_FE(array_diff, NULL) PHP_FE(array_diff_assoc, NULL)
--- php_array.h 2002-12-31 14:35:32.000000000 -0200
+++ /home/aluno/php-4.3.8-new/ext/standard/php_array.h 2004-07-20
14:04:38.000000000 -0300
@@ -75,6 +75,7 @@
PHP_FUNCTION(array_rand);
PHP_FUNCTION(array_unique);
PHP_FUNCTION(array_intersect);
+PHP_FUNCTION(array_intersect_key);
PHP_FUNCTION(array_intersect_assoc);
PHP_FUNCTION(array_diff);
PHP_FUNCTION(array_diff_assoc);
Andrey Hristov wrote:
is "make test" showing problems? (i am just currious).
I will try to review the patch later today (atm i am sick).
Which also reminds me that we still dont have a function to merge a
multi dimensional array without messing with the array structures (which
array_merge_recursive()
does if it finds any overlap).
http://bugs.php.net/bug.php?id=6911
regards,
Lukas Smith
Andrey Hristov wrote:
is "make test" showing problems? (i am just currious).
I will try to review the patch later today (atm i am sick).
Nope. Make test shows the same errors before and after the patch.
I decided to attach the patch since it will keep tabs...
Cristiano Duarte
Hallo Cristiano,
these 2 function will be added to HEAD in few minutes. I see that the
patch is kind of trivial and won't hurt anything :) (INTERSECT_KEY
is just INTERSECT_ASSOC but no data comparison performed).
I will add also array_diff_key()
and array_diff_ukey()
cheers,
andrey
P.S.
Andi: I think the changes are minimal, so is it possible to merge into 5_0 ?
Cristiano Duarte wrote:
Andrey Hristov wrote:
is "make test" showing problems? (i am just currious).
I will try to review the patch later today (atm i am sick).Nope. Make test shows the same errors before and after the patch.
I decided to attach the patch since it will keep tabs...
Cristiano Duarte
--- array.c 2004-07-11 18:15:04.000000000 -0300
+++ /home/aluno/php-5.0.0-new/ext/standard/array.c 2004-07-21 11:47:58.000000000 -0300
@@ -77,6 +77,7 @@#define DIFF_NORMAL 0
#define DIFF_ASSOC 1
+#define DIFF_KEY 2
#define DIFF_COMP_DATA_INTERNAL 0
#define DIFF_COMP_DATA_USER 1
#define DIFF_COMP_KEY_INTERNAL 0
@@ -84,6 +85,7 @@#define INTERSECT_NORMAL 0
#define INTERSECT_ASSOC 1
+#define INTERSECT_KEY 2
#define INTERSECT_COMP_DATA_INTERNAL 0
#define INTERSECT_COMP_DATA_USER 1
#define INTERSECT_COMP_KEY_INTERNAL 0
@@ -2797,7 +2799,8 @@
php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
return;
}
- } else if (behavior == INTERSECT_ASSOC) {
- } else if ((behavior == INTERSECT_ASSOC)
||(behavior == INTERSECT_KEY)) { intersect_key_compare_func = array_key_compare; if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL &&
@@ -2910,7 +2913,7 @@
*list = NULL;
if (behavior == INTERSECT_NORMAL) {
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), intersect_data_compare_func TSRMLS_CC);
} else if (behavior == INTERSECT_ASSOC) {
} else if ((behavior == INTERSECT_ASSOC) || (behavior == INTERSECT_KEY)) { zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), intersect_key_compare_func TSRMLS_CC); }
}
@@ -2926,7 +2929,8 @@/* go through the lists and look for common values */
while (*ptrs[0]) {
if (behavior == INTERSECT_ASSOC
if ((behavior == INTERSECT_ASSOC
|| behavior == INTERSECT_KEY) && key_compare_type == INTERSECT_COMP_KEY_USER) {
@@ -2938,11 +2942,11 @@
while (*ptrs[i] && (0 < (c = intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)))) {
ptrs[i]++;
}
} else if (behavior == INTERSECT_ASSOC) {
} else if (behavior == INTERSECT_ASSOC || behavior == INTERSECT_KEY) { while (*ptrs[i] && (0 < (c = intersect_key_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)))) { ptrs[i]++; }
if (!c && *ptrs[i]) { /* this means that ptrs[i] is not `NULL` so we can compare */
if ((!c && *ptrs[i]) && (behavior == INTERSECT_ASSOC)) { /* this means that ptrs[i] is not `NULL` so we can compare */ /* and "c==0" is from last operation */ if (data_compare_type == INTERSECT_COMP_DATA_USER) { BG(user_compare_func_name) = args[arr_argc];
@@ -2996,7 +3000,7 @@
if (0 <= intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)) {
break;
}
} else if (behavior == INTERSECT_ASSOC) {
} else if (behavior == INTERSECT_ASSOC || behavior == INTERSECT_KEY) { /* no need of looping because indexes are unique */ break; }
@@ -3012,7 +3016,7 @@
if (intersect_data_compare_func(ptrs[0]-1, ptrs[0] TSRMLS_CC)) {
break;
}
} else if (behavior == INTERSECT_ASSOC) {
} else if (behavior == INTERSECT_ASSOC || behavior == INTERSECT_KEY) { /* no need of looping because indexes are unique */ break; }
@@ -3050,7 +3054,27 @@
}
/* }}} */+/* {{{ proto array array_intersect_key(array arr1, array arr2 [,
+array ...])
- Returns the entries of arr1 that have keys which are present in all the other arguments. */
+PHP_FUNCTION(array_intersect_key)
+{- php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY,
INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_INTERNAL);
+}
+/* }}} */
+/* {{{ proto array array_uintersect_key(array arr1, array arr2 [, array ...], callback data_compare_func)
- Returns the entries of arr1 that have keys which are present in all the other arguments. Key is compared by using an user-supplied callback. */
+PHP_FUNCTION(array_uintersect_key)
+{- php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY,
INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER);
+}
+/* }}} */
/* {{{ proto array array_intersect_assoc(array arr1, array arr2 [, array ...])
Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check */
PHP_FUNCTION(array_intersect_assoc)
@@ -3151,7 +3175,8 @@
php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
return;
}
- } else if (behavior == DIFF_ASSOC) {
- } else if ((behavior == DIFF_ASSOC)
|| (behavior == DIFF_KEY)) { diff_key_compare_func = array_key_compare; if (data_compare_type == DIFF_COMP_DATA_INTERNAL &&
@@ -3264,7 +3289,7 @@
*list = NULL;
if (behavior == DIFF_NORMAL) {
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), diff_data_compare_func TSRMLS_CC);
} else if (behavior == DIFF_ASSOC) {
} else if ((behavior == DIFF_ASSOC) || (behavior == DIFF_KEY)) { zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), diff_key_compare_func TSRMLS_CC); }
}
@@ -3280,7 +3305,8 @@/* go through the lists and look for values of ptr[0] that are not in the others */
while (*ptrs[0]) {
if (behavior == DIFF_ASSOC
if ((behavior == DIFF_ASSOC
|| behavior == DIFF_KEY) && key_compare_type == DIFF_COMP_KEY_USER) {
@@ -3292,7 +3318,7 @@
while (*ptrs[i] && (0 < (c = diff_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)))) {
ptrs[i]++;
}
} else if (behavior == DIFF_ASSOC) {
} else if ((behavior == DIFF_ASSOC) || (behavior == DIFF_KEY)) { while (*ptrs[i] && (0 < (c = diff_key_compare_func(ptrs[0], ptrs[i] TSRMLS_CC)))) { ptrs[i]++; }
@@ -3337,7 +3363,7 @@
if (diff_data_compare_func(ptrs[0] - 1, ptrs[0] TSRMLS_CC)) {
break;
}
} else if (behavior == DIFF_ASSOC) {
} else if ((behavior == DIFF_ASSOC) || (behavior == DIFF_KEY)) { /* in this case no array_key_compare is needed */ break; }
@@ -3353,7 +3379,7 @@
if (diff_data_compare_func(ptrs[0]-1, ptrs[0] TSRMLS_CC)) {
break;
}
} else if (behavior == DIFF_ASSOC) {
} else if ((behavior == DIFF_ASSOC) || (behavior == DIFF_KEY)) { /* in this case no array_key_compare is needed */ break; }
@@ -3392,6 +3418,23 @@
}
/* }}} */+/* {{{ proto array array_diff_key(array arr1, array arr2 [, array ...])
- Returns the entries of arr1 that have keys which are not present in any of the others arguments */
+PHP_FUNCTION(array_diff_key)
+{- php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_KEY,
DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_INTERNAL);
+}
+/* }}} */
+/* {{{ proto array array_udiff_key(array arr1, array arr2 [, array ...], callback key_comp_func)
- Returns the entries of arr1 that have keys which are not present in any of the others arguments. Keys are compared by user supplied function. */
+PHP_FUNCTION(array_udiff_key)
+{- php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_KEY,
DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER);
+}
+/* }}} *//* {{{ 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 but do additional checks whether the keys are equal */
--- basic_functions.c 2004-06-27 18:49:47.000000000 -0300
+++ /home/aluno/php-5.0.0-new/ext/standard/basic_functions.c 2004-07-21 11:36:34.000000000 -0300
@@ -780,12 +780,16 @@
PHP_FE(array_unique, NULL)
PHP_FE(array_intersect, NULL)
PHP_FE(array_uintersect, NULL)
- PHP_FE(array_intersect_key, NULL)
- PHP_FE(array_uintersect_key, NULL)
PHP_FE(array_intersect_assoc, NULL)
PHP_FE(array_uintersect_assoc, NULL)
PHP_FE(array_intersect_uassoc, NULL)
PHP_FE(array_uintersect_uassoc, NULL)
PHP_FE(array_diff, NULL)
PHP_FE(array_udiff, NULL)- PHP_FE(array_diff_key, NULL)
- PHP_FE(array_udiff_key, NULL)
PHP_FE(array_diff_assoc, NULL)
PHP_FE(array_udiff_assoc, NULL)
PHP_FE(array_diff_uassoc, NULL)
--- php_array.h 2004-01-08 15:32:51.000000000 -0200
+++ /home/aluno/php-5.0.0-new/ext/standard/php_array.h 2004-07-21 11:36:54.000000000 -0300
@@ -77,12 +77,16 @@
PHP_FUNCTION(array_unique);
PHP_FUNCTION(array_intersect);
PHP_FUNCTION(array_uintersect);
+PHP_FUNCTION(array_intersect_key);
+PHP_FUNCTION(array_uintersect_key);
PHP_FUNCTION(array_intersect_assoc);
PHP_FUNCTION(array_uintersect_assoc);
PHP_FUNCTION(array_intersect_uassoc);
PHP_FUNCTION(array_uintersect_uassoc);
PHP_FUNCTION(array_diff);
PHP_FUNCTION(array_udiff);
+PHP_FUNCTION(array_diff_key);
+PHP_FUNCTION(array_udiff_key);
PHP_FUNCTION(array_diff_assoc);
PHP_FUNCTION(array_udiff_assoc);
PHP_FUNCTION(array_diff_uassoc);
Andrey Hristov wrote:
Hallo Cristiano,
these 2 function will be added to HEAD in few minutes. I see that the
patch is kind of trivial and won't hurt anything :) (INTERSECT_KEY
is just INTERSECT_ASSOC but no data comparison performed).
I will add alsoarray_diff_key()
andarray_diff_ukey()
I have added these already. :-)
Cristiano Duarte
Well, i think I have found a buggie (not related to these functions and I want to
investigate it). Thus I will delay the commit.
Cristiano Duarte wrote:
Andrey Hristov wrote:
Hallo Cristiano,
these 2 function will be added to HEAD in few minutes. I see that the
patch is kind of trivial and won't hurt anything :) (INTERSECT_KEY
is just INTERSECT_ASSOC but no data comparison performed).
I will add alsoarray_diff_key()
andarray_diff_ukey()
I have added these already. :-)
I see :)
andrey
Andrey Hristov wrote:
Hallo Cristiano,
these 2 function will be added to HEAD in few minutes. I see that the
patch is kind of trivial and won't hurt anything :) (INTERSECT_KEY
is just INTERSECT_ASSOC but no data comparison performed).
I will add alsoarray_diff_key()
andarray_diff_ukey()
I changed the function name from array_udiff_key to array_diff_ukey.
Is this ok ? Patch attached.
Cristiano Duarte
Cristiano Duarte wrote:
Andrey Hristov wrote:
Hallo Cristiano,
these 2 function will be added to HEAD in few minutes. I see that the
patch is kind of trivial and won't hurt anything :) (INTERSECT_KEY
is just INTERSECT_ASSOC but no data comparison performed).
I will add alsoarray_diff_key()
andarray_diff_ukey()
I changed the function name from array_udiff_key to array_diff_ukey.
Is this ok ? Patch attached.
Well, my patch for array_diff_key()
and array_diff_ukey()
looked like yours
but when writing the regression tests I spotted a bug. I thought it is not related
to the new functions. After some testing I found the problem and it was related
to array_diff_*key(). I have placed a comment in the source at about line 3364.
cheers,
andrey