Add remove(), removeAll() and retainAll(). Fix readme.

This commit is contained in:
CismonX 2018-05-05 18:29:14 +08:00
parent bdaa0b7913
commit a57c1ba965
5 changed files with 102 additions and 13 deletions

View File

@ -20,7 +20,7 @@ See [stubs](stubs/) directory for signature of all classes and methods of this e
The `Collection` class implements `ArrayAccess` and `Countable` interface internally, you can treat an instance of `Collection` as an `ArrayObject`.
* The `isset()`, `unset()` keywords can be used on elements of `Collection`.
* Elements can be accessed via property (string keys only) and bracket expression.
* Elements can be accessed via property and bracket expression.
* `empty()`, `count()` can be used on instance of `Collection`.
* Elements can be traversed via `foreach()` keyword.
@ -48,7 +48,7 @@ $names = Collection::init($employees)
->sortedByDescending(function ($value) {
return $value['age'];
})
->map(function ($value) {
->mapValues(function ($value) {
return $value['name'];
})
->toArray();

View File

@ -5,6 +5,7 @@
//
#include <php.h>
#include <stdint.h>
#include "php_collections.h"
#include "php_collections_me.h"
@ -1142,17 +1143,77 @@ PHP_METHOD(Collection, reduceRight)
PHP_METHOD(Collection, remove)
{
zval* key;
zval* value = NULL;
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_ZVAL(key)
Z_PARAM_OPTIONAL
Z_PARAM_ZVAL(value)
ZEND_PARSE_PARAMETERS_END();
zend_array* current = COLLECTION_FETCH_CURRENT();
zval* found;
if (Z_TYPE_P(key) == IS_LONG) {
if (value == NULL)
RETURN_BOOL(zend_hash_index_del(current, Z_LVAL_P(key)) == SUCCESS);
found = zend_hash_index_find(current, Z_LVAL_P(key));
if (found == NULL || fast_equal_check_function(found, value) == 0)
RETURN_FALSE;
RETURN_BOOL(zend_hash_index_del(current, Z_LVAL_P(key)) == SUCCESS);
}
if (Z_TYPE_P(key) == IS_STRING) {
if (value == NULL)
RETURN_BOOL(zend_hash_del(current, Z_STR_P(key)) == SUCCESS);
found = zend_hash_find(current, Z_STR_P(key));
if (found == NULL || fast_equal_check_function(found, value) == 0)
RETURN_FALSE;
RETURN_BOOL(zend_hash_del(current, Z_STR_P(key)) == SUCCESS);
}
ERR_BAD_KEY_TYPE();
RETVAL_FALSE;
}
PHP_METHOD(Collection, removeAll)
{
zend_fcall_info fci;
zend_fcall_info_cache fcc;
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_FUNC(fci, fcc)
ZEND_PARSE_PARAMETERS_END();
zend_array* current = COLLECTION_FETCH_CURRENT();
SEPARATE_CURRENT_COLLECTION(current);
if (EX_NUM_ARGS() == 0) {
zend_hash_clean(current);
return;
}
INIT_FCI(2);
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
zend_hash_del_bucket(current, bucket);
ZEND_HASH_FOREACH_END();
}
PHP_METHOD(Collection, retainAll)
{
zend_fcall_info fci;
zend_fcall_info_cache fcc;
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_FUNC(fci, fcc)
ZEND_PARSE_PARAMETERS_END();
zend_array* current = COLLECTION_FETCH_CURRENT();
SEPARATE_CURRENT_COLLECTION(current);
if (EX_NUM_ARGS() == 0) {
zend_hash_clean(current);
return;
}
INIT_FCI(2);
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (!zend_is_true(&retval))
zend_hash_del_bucket(current, bucket);
ZEND_HASH_FOREACH_END();
}
PHP_METHOD(Collection, reverse)
@ -1179,12 +1240,13 @@ PHP_METHOD(Collection, set)
Z_PARAM_ZVAL(value)
ZEND_PARSE_PARAMETERS_END();
zend_array* current = COLLECTION_FETCH_CURRENT();
SEPARATE_CURRENT_COLLECTION(current);
if (Z_TYPE_P(key) == IS_STRING)
if (Z_TYPE_P(key) == IS_STRING) {
SEPARATE_CURRENT_COLLECTION(current);
zend_hash_update(current, Z_STR_P(key), value);
else if (Z_TYPE_P(key) == IS_LONG)
} else if (Z_TYPE_P(key) == IS_LONG) {
SEPARATE_CURRENT_COLLECTION(current);
zend_hash_index_update(current, Z_LVAL_P(key), value);
else
} else
ERR_BAD_KEY_TYPE();
}

View File

@ -680,14 +680,16 @@ class Collection implements ArrayAccess, Countable
*
* @param int|string $key
* @param mixed $value[optional]
* @return bool
*/
function remove($key, $value) {}
/**
* Removes all elements from this collection that match the given predicate.
* Removes all elements from this collection that match the given predicate. If predicate is not
* provided, all elements will be removed.
*
* @param callable $predicate ($value, $key) -> bool
* @return bool
* @param callable $predicate[optional] ($value, $key) -> bool
* @return void
*/
function removeAll($predicate) {}
@ -695,7 +697,7 @@ class Collection implements ArrayAccess, Countable
* Retains only elements of this collection that match the given predicate.
*
* @param callable $predicate ($value, $key) -> bool
* @return bool
* @return void
*/
function retainAll($predicate) {}

View File

@ -13,5 +13,9 @@ if ($collection->toArray() != $array)
if ($collection->get('a') != $array['a'] ||
$collection->get('f', function ($key) { return $key; }) != 'f')
echo 'Collection::get() failed.', PHP_EOL;
if (!$collection->remove('a') || !is_null($collection->get('a')))
echo 'Collection::remove() failed.', PHP_EOL;
if ($collection->remove('c', 'e') || $collection->get('c') != 'd')
echo 'Collection::remove() failed.', PHP_EOL;
?>
--EXPECT--

View File

@ -0,0 +1,21 @@
--TEST--
Test Collection::removeAll() and Collection::retainAll().
--FILE--
<?php
$array = ['a' => 4, 'b' => 1, 'c' => 9, 'd' => -2, 'e' => 0];
$pred_is_odd = function ($value) {
return $value % 2;
};
$collection = Collection::init($array);
$collection->removeAll($pred_is_odd);
if ($collection->toArray() != ['a' => 4, 'd' => -2, 'e' => 0])
echo 'Collection::removeAll() failed.', PHP_EOL;
$collection->removeAll();
if ($collection->toArray() != [])
echo 'Collection::removeAll() failed.', PHP_EOL;
$collection = Collection::init($array);
$collection->retainAll($pred_is_odd);
if ($collection->toArray() != ['b' => 1, 'c' => 9])
echo 'Collection::retainAll() failed.', PHP_EOL;
?>
--EXPECT--