Add `takeWhile()` and `takeLastWhile()`.

This commit is contained in:
CismonX 2018-06-03 19:18:40 +08:00
parent 9666bc61d3
commit 441ca5be72
3 changed files with 75 additions and 4 deletions

View File

@ -1429,6 +1429,8 @@ PHP_METHOD(Collection, take)
continue;
--n;
Z_TRY_ADDREF(bucket->val);
// Works for any zend_array, however, it doesn't make sense if you use any of these methods
// on non-packed zend_arrays.
if (bucket->key)
zend_hash_add_new(new_collection, bucket->key, &bucket->val);
else if (HT_IS_PACKED(current))
@ -1481,12 +1483,63 @@ PHP_METHOD(Collection, takeLast)
PHP_METHOD(Collection, takeLastWhile)
{
zend_fcall_info fci;
zend_fcall_info_cache fcc;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_FUNC(fci, fcc)
ZEND_PARSE_PARAMETERS_END();
INIT_FCI(2);
zend_array* current = COLLECTION_FETCH_CURRENT();
ARRAY_NEW_EX(new_collection, current);
uint32_t num_elements = zend_hash_num_elements(current);
Bucket* taken[num_elements];
ZEND_HASH_REVERSE_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval))
taken[--num_elements] = bucket;
else
break;
ZEND_HASH_FOREACH_END();
memset(&taken[0], NULL, num_elements * sizeof(Bucket*));
int i = 0;
for (; i < zend_hash_num_elements(current); ++i) {
Bucket* bucket = taken[i];
if (bucket == NULL)
continue;
Z_TRY_ADDREF(bucket->val);
if (bucket->key)
zend_hash_add_new(new_collection, bucket->key, &bucket->val);
else if (HT_IS_PACKED(current))
zend_hash_next_index_insert(new_collection, &bucket->val);
else
zend_hash_index_add_new(new_collection, bucket->h, &bucket->val);
}
RETVAL_NEW_COLLECTION(new_collection);
}
PHP_METHOD(Collection, takeWhile)
{
zend_fcall_info fci;
zend_fcall_info_cache fcc;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_FUNC(fci, fcc)
ZEND_PARSE_PARAMETERS_END();
INIT_FCI(2);
zend_array* current = COLLECTION_FETCH_CURRENT();
ARRAY_NEW_EX(new_collection, current);
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (zend_is_true(&retval)) {
if (bucket->key)
zend_hash_add_new(new_collection, bucket->key, &bucket->val);
else if (HT_IS_PACKED(current))
zend_hash_next_index_insert(new_collection, &bucket->val);
else
zend_hash_index_add_new(new_collection, bucket->h, &bucket->val);
} else
break;
ZEND_HASH_FOREACH_END();
RETVAL_NEW_COLLECTION(new_collection);
}
PHP_METHOD(Collection, toArray)

View File

@ -840,7 +840,7 @@ class Collection implements ArrayAccess, Countable
/**
* Returns a collection containing last elements satisfying the given predicate.
*
* @param $predicate ($value, $key) -> bool
* @param callable $predicate ($value, $key) -> bool
* @return Collection
*/
function takeLastWhile($predicate) {}
@ -848,7 +848,7 @@ class Collection implements ArrayAccess, Countable
/**
* Returns a collection containing first elements satisfying the given predicate.
*
* @param $predicate ($value, $key) -> bool
* @param callable $predicate ($value, $key) -> bool
* @return Collection
*/
function takeWhile($predicate) {}

18
tests/034-take-while.phpt Normal file
View File

@ -0,0 +1,18 @@
--TEST--
Test Collection::takeWhile() and Collection::takeLastWhile().
--FILE--
<?php
$array = ['a', 'b', 'C', 'D', 'e'];
$collection = Collection::init($array);
$collection1 = $collection->takeWhile(function ($value) {
return ord($value) > ord('Z');
});
if ($collection1->toArray() != ['a', 'b'])
echo 'Collection::takeWhile() failed.', PHP_EOL;
$collection2 = $collection->takeLastWhile(function ($value) {
return $value != 'b';
});
if ($collection2->toArray() != ['C', 'D', 'e'])
echo 'Collection::takeLastWhile() failed.', PHP_EOL;
?>
--EXPECT--