From dae53dfc69c574549c6e25c5786e215b991cdfef Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 19 Dec 2014 05:06:54 +0300 Subject: [PATCH] Improved array_diff() function (use simple and more efficient algorithm). --- ext/standard/array.c | 65 ++++++++++++++++++- .../tests/array/array_diff_variation9.phpt | 62 ++---------------- 2 files changed, 68 insertions(+), 59 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 58bca29da8..041c68558e 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3979,7 +3979,70 @@ PHP_FUNCTION(array_diff_ukey) 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, DIFF_NORMAL, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_INTERNAL); + zval *args; + int argc, i; + uint32_t num; + HashTable exclude; + zval *value; + zend_string *str, *key; + zend_long idx; + + if (ZEND_NUM_ARGS() < 2) { + php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS()); + return; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) { + return; + } + + if (Z_TYPE(args[0]) != IS_ARRAY) { + php_error_docref(NULL, E_WARNING, "Argument #1 is not an array"); + RETURN_NULL(); + } + + /* count number of elements */ + num = 0; + for (i = 1; i < argc; i++) { + if (Z_TYPE(args[i]) != IS_ARRAY) { + php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1); + RETURN_NULL(); + } + num += zend_hash_num_elements(Z_ARRVAL(args[i])); + } + + if (num == 0) { + ZVAL_COPY(return_value, &args[0]); + return; + } + + /* create exclude map */ + zend_hash_init(&exclude, num, NULL, NULL, 0); + for (i = 1; i < argc; i++) { + ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) { + str = zval_get_string(value); + zend_hash_add_empty_element(&exclude, str); + zend_string_release(str); + } ZEND_HASH_FOREACH_END(); + } + + /* copy all elements of first array that are not in exclude set */ + array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0]))); + ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(args[0]), idx, key, value) { + str = zval_get_string(value); + if (!zend_hash_exists(&exclude, str)) { + if (key) { + zval_add_ref(value); + zend_hash_add_new(Z_ARRVAL_P(return_value), key, value); + } else { + zval_add_ref(value); + zend_hash_index_add_new(Z_ARRVAL_P(return_value), idx, value); + } + } + zend_string_release(str); + } ZEND_HASH_FOREACH_END(); + + zend_hash_destroy(&exclude); } /* }}} */ diff --git a/ext/standard/tests/array/array_diff_variation9.phpt b/ext/standard/tests/array/array_diff_variation9.phpt index 1bf1f1c2ac..83302378f0 100644 --- a/ext/standard/tests/array/array_diff_variation9.phpt +++ b/ext/standard/tests/array/array_diff_variation9.phpt @@ -1,5 +1,7 @@ --TEST-- Test array_diff() function : usage variations - multidimensional arrays +--INI-- +error_reporting=E_ALL & ~E_NOTICE --FILE-- ---EXPECTF-- +--EXPECT-- *** Testing array_diff() : usage variations *** -- Compare two 2-D arrays -- - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d array(0) { } - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d array(0) { } @@ -101,16 +71,6 @@ array(3) { } -- Compare a subarray from one 2-D array and one 2-D array -- - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d array(3) { [0]=> int(1) @@ -119,20 +79,6 @@ array(3) { [2]=> int(3) } - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d - -Notice: Array to string conversion in %sarray_diff_variation9.php on line %d array(2) { ["sub_array1"]=> array(3) { @@ -153,4 +99,4 @@ array(2) { string(1) "c" } } -Done \ No newline at end of file +Done -- 2.40.0