Add `sum()` and `sumBy()`.

This commit is contained in:
CismonX 2018-09-06 10:30:18 +08:00
parent cf8092f6d2
commit f3096fe30a
5 changed files with 116 additions and 0 deletions

View File

@ -206,6 +206,8 @@ const zend_function_entry collection_methods[] = {
PHP_ME(Collection, sortedByDescending, selector_flags_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, sortedDescending, flags_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, sortedWith, comparator_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, sum, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Collection, sumBy, selector_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, take, n_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, takeLast, n_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, takeLastWhile, predicate_arginfo, ZEND_ACC_PUBLIC)

View File

@ -2702,6 +2702,71 @@ PHP_METHOD(Collection, sortedWith)
RETVAL_NEW_COLLECTION(sorted_with);
}
PHP_METHOD(Collection, sum)
{
zend_array* current = COLLECTION_FETCH_CURRENT();
zval sum;
ZVAL_NULL(&sum);
ZEND_HASH_FOREACH_VAL(current, zval* val)
if (UNEXPECTED(ZVAL_IS_NULL(&sum))) {
if (Z_TYPE_P(val) == IS_LONG) {
ZVAL_LONG(&sum, 0);
} else if (EXPECTED(Z_TYPE_P(val) == IS_DOUBLE)) {
ZVAL_DOUBLE(&sum, 0.0);
} else {
ERR_NOT_NUMERIC();
RETURN_NULL();
}
}
if (Z_TYPE_P(val) == IS_LONG) {
Z_LVAL(sum) += Z_LVAL_P(val);
} else if (EXPECTED(Z_TYPE_P(val) == IS_DOUBLE)) {
Z_DVAL(sum) += Z_DVAL_P(val);
} else {
ERR_NOT_NUMERIC();
RETURN_NULL();
}
ZEND_HASH_FOREACH_END();
RETVAL_ZVAL(&sum, 0, 0);
}
PHP_METHOD(Collection, sumBy)
{
zend_fcall_info fci;
zend_fcall_info_cache fcc;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_FUNC(fci, fcc)
ZEND_PARSE_PARAMETERS_END();
zend_array* current = COLLECTION_FETCH_CURRENT();
zval sum;
ZVAL_NULL(&sum);
INIT_FCI(&fci, 2);
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
CALLBACK_KEYVAL_INVOKE(params, bucket);
if (UNEXPECTED(ZVAL_IS_NULL(&sum))) {
if (Z_TYPE(retval) == IS_LONG) {
ZVAL_LONG(&sum, 0);
} else if (EXPECTED(Z_TYPE(retval) == IS_DOUBLE)) {
ZVAL_DOUBLE(&sum, 0.0);
} else {
ERR_NOT_NUMERIC();
zval_ptr_dtor(&retval);
RETURN_NULL();
}
}
if (Z_TYPE(retval) == IS_LONG) {
Z_LVAL(sum) += Z_LVAL(retval);
} else if (EXPECTED(Z_TYPE(retval) == IS_DOUBLE)) {
Z_DVAL(sum) += Z_DVAL(retval);
} else {
ERR_NOT_NUMERIC();
zval_ptr_dtor(&retval);
RETURN_NULL();
}
ZEND_HASH_FOREACH_END();
RETVAL_ZVAL(&sum, 0, 0);
}
PHP_METHOD(Collection, take)
{
zend_long n;

View File

@ -94,6 +94,8 @@ PHP_METHOD(Collection, sortedBy);
PHP_METHOD(Collection, sortedByDescending);
PHP_METHOD(Collection, sortedDescending);
PHP_METHOD(Collection, sortedWith);
PHP_METHOD(Collection, sum);
PHP_METHOD(Collection, sumBy);
PHP_METHOD(Collection, take);
PHP_METHOD(Collection, takeLast);
PHP_METHOD(Collection, takeLastWhile);

View File

@ -807,6 +807,27 @@ class Collection implements ArrayAccess, Countable
*/
function sortedWith($comparator) {}
/**
* Returns the sum of all elements in the collection.
*
* All elements should be of the same type, int or double. Otherwise result is undefined.
*
* @return int|double|null
*/
function sum() {}
/**
* Returns the sum of all values produced by selector function applied to each element
* in the collection.
*
* All return values of the selector function should be of the same type, int or double.
* Otherwise result is undefined.
*
* @param callable $selector ($value, $key) -> int|double
* @return int|double|null
*/
function sumBy($selector) {}
/**
* Returns a collection containing first n elements.
*

26
tests/054-sum-by.phpt Normal file
View File

@ -0,0 +1,26 @@
--TEST--
Test Collection::sum() and Collection::sumBy().
--FILE--
<?php
$array = [];
for ($i = 0; $i < 50; ++$i) {
$array[] = random_int(1, 50);
}
$collection = Collection::init($array);
$sum = array_sum($array);
if ($collection->sum() != $sum) {
echo 'Collection::sum() failed.', PHP_EOL;
}
$array = array_map(function ($value) {
return [$value, floatval($value / random_int(3, 7))];
}, $array);
$collection = Collection::init($array);
$sum = array_sum(array_column($array, 1));
$sum_by = function ($value) {
return $value[1];
};
if ($collection->sumBy($sum_by) != $sum) {
echo 'Collection::sumBy() failed.', PHP_EOL;
}
?>
--EXPECT--