diff --git a/src/collections_me.c b/src/collections_me.c index e2bd2bf..d42e8aa 100644 --- a/src/collections_me.c +++ b/src/collections_me.c @@ -160,6 +160,8 @@ const zend_function_entry collection_methods[] = { PHP_ME(Collection, indexOfLast, predicate_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, init, elements_arginfo, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(Collection, intersect, other_arginfo, ZEND_ACC_PUBLIC) + PHP_ME(Collection, intersectKeys, other_arginfo, ZEND_ACC_PUBLIC) + PHP_ME(Collection, intersectValues, other_arginfo, ZEND_ACC_PUBLIC) PHP_ME(Collection, isEmpty, NULL, ZEND_ACC_PUBLIC) PHP_ME(Collection, isNotEmpty, NULL, ZEND_ACC_PUBLIC) PHP_ME(Collection, keys, NULL, ZEND_ACC_PUBLIC) diff --git a/src/collections_methods.c b/src/collections_methods.c index 068d728..9ca99dd 100644 --- a/src/collections_methods.c +++ b/src/collections_methods.c @@ -1781,7 +1781,74 @@ PHP_METHOD(Collection, init) PHP_METHOD(Collection, intersect) { - + zval* elements; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ZVAL(elements) + ZEND_PARSE_PARAMETERS_END(); + ELEMENTS_VALIDATE(elements, ERR_BAD_ARGUMENT_TYPE, return); + zend_array* current = COLLECTION_FETCH_CURRENT(); + ARRAY_NEW(intersected, 8); + equal_check_func_t eql = NULL; + ZEND_HASH_FOREACH_BUCKET(elements_arr, Bucket* bucket) + if (UNEXPECTED(eql == NULL)) + { + eql = equal_check_func_init(&bucket->val); + } + if (bucket->key) + { + zval* result = zend_hash_find(current, bucket->key); + if (result && eql(&bucket->val, result)) + { + zend_hash_add(intersected, bucket->key, result); + Z_TRY_ADDREF_P(result); + } + } + else + { + zval* result = zend_hash_index_find(current, bucket->h); + if (result && eql(&bucket->val, result)) + { + zend_hash_index_add(intersected, bucket->h, result); + Z_TRY_ADDREF_P(result); + } + } + ZEND_HASH_FOREACH_END(); + RETVAL_NEW_COLLECTION(intersected); +} + +PHP_METHOD(Collection, intersectKeys) +{ + zval* elements; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ZVAL(elements) + ZEND_PARSE_PARAMETERS_END(); + ELEMENTS_VALIDATE(elements, ERR_BAD_ARGUMENT_TYPE, return); + zend_array* current = COLLECTION_FETCH_CURRENT(); + ARRAY_NEW(intersected, 8); + ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket) + if (bucket->key) + { + if (zend_hash_exists(elements_arr, bucket->key)) + { + zend_hash_add(intersected, bucket->key, &bucket->val); + Z_TRY_ADDREF(bucket->val); + } + } + else + { + if (zend_hash_index_exists(elements_arr, bucket->h)) + { + zend_hash_index_add(intersected, bucket->h, &bucket->val); + Z_TRY_ADDREF(bucket->val); + } + } + ZEND_HASH_FOREACH_END(); + RETVAL_NEW_COLLECTION(intersected); +} + +PHP_METHOD(Collection, intersectValues) +{ + } PHP_METHOD(Collection, isEmpty) diff --git a/src/php_collections_me.h b/src/php_collections_me.h index c5ec561..1dc4d72 100644 --- a/src/php_collections_me.h +++ b/src/php_collections_me.h @@ -48,6 +48,8 @@ PHP_METHOD(Collection, indexOfFirst); PHP_METHOD(Collection, indexOfLast); PHP_METHOD(Collection, init); PHP_METHOD(Collection, intersect); +PHP_METHOD(Collection, intersectKeys); +PHP_METHOD(Collection, intersectValues); PHP_METHOD(Collection, isEmpty); PHP_METHOD(Collection, isNotEmpty); PHP_METHOD(Collection, keys); diff --git a/stubs/Collection.php b/stubs/Collection.php index f4d1de4..cdd8bfe 100644 --- a/stubs/Collection.php +++ b/stubs/Collection.php @@ -373,13 +373,34 @@ class Collection implements ArrayAccess, Countable static function init($elements) {} /** - * Returns a collection containing all elements that are contained by both this collection and the - * specified collection. + * Returns a collection containing all key-value pairs that are contained by both this collection + * and the specified collection. * * @param array|Collection $other + * @return Collection */ function intersect($other) {} + /** + * Returns a collection containing all elements with keys contained by both this collection + * and the specified collection. Values are that of the original collection. + * + * @param array|Collection $other + * @return Collection + */ + function intersectKeys($other) {} + + /** + * Returns a collection containing all elements with values contained by both this collection + * and the specified collection. Keys are that of the original collection. + * + * Duplicate values will be removed. + * + * @param array|Collection $other + * @return Collection + */ + function intersectValues($other) {} + /** * Returns true if the collection is empty. * @@ -389,6 +410,8 @@ class Collection implements ArrayAccess, Countable /** * Returns true if the collection is not empty. + * + * @return bool */ function isNotEmpty() {} diff --git a/tests/051-intersect-keys.phpt b/tests/051-intersect-keys.phpt new file mode 100644 index 0000000..3b9b955 --- /dev/null +++ b/tests/051-intersect-keys.phpt @@ -0,0 +1,27 @@ +--TEST-- +Test Collection::intersect() and Collection::intersectKeys(). +--FILE-- + 'b', + 'c' => 'd', + 'e' => 'f' +]; +$array1 = [ + 'a' => 'c', + 'b' => strval(12), + 'c' => 'd', + 'g' => 'h' +]; +$collection = Collection::init($array); +$intersected = array_intersect_assoc($array, $array1); +if ($collection->intersect($array1)->toArray() != $intersected) { + echo 'Collection::intersect() failed.', PHP_EOL; +} +$collection1 = Collection::init($array1); +$intersected = array_intersect_key($array, $array1); +if ($collection->intersectKeys($collection1)->toArray() != $intersected) { + echo 'Collection::intersectKeys() failed.', PHP_EOL; +} +?> +--EXPECT--