Add `average()` and `containsAll()`. Update README.

This commit is contained in:
CismonX 2018-03-28 13:02:51 +08:00
parent 8d62f9a288
commit 4a3c28b4b3
5 changed files with 78 additions and 18 deletions

View File

@ -30,14 +30,15 @@ $employees = [
// sorted by the descending order of their age.
$names = Collection::init($employees)
->filter(function ($it) {
return $it->get('sex') == 'male';
return $it['sex'] == 'male';
})
->sortedByDescending(function ($it) {
return $it->get('age');
return $it['age'];
})
->map(function ($it) {
return $it->get('name');
return $it['name'];
})
->toArray();
// You got $names == ['David', 'Benjamin', 'Bob'].
```

View File

@ -26,7 +26,7 @@ PHP_MINIT_FUNCTION(collections)
zend_class_entry collection_ce;
INIT_CLASS_ENTRY_EX(collection_ce, "Collection", sizeof "Collection" - 1, collection_methods);
collections_collection_ce = zend_register_internal_class(&collection_ce);
zend_declare_property_null(collections_collection_ce, "_a", sizeof "_a" - 1, ZEND_ACC_PRIVATE);
zend_declare_property_null(collections_collection_ce, "_", sizeof "_" - 1, ZEND_ACC_PRIVATE);
zend_class_entry pair_ce;
INIT_CLASS_ENTRY_EX(pair_ce, "Pair", sizeof "Pair" - 1, pair_methods);
collections_pair_ce = zend_register_internal_class(&pair_ce);

View File

@ -23,20 +23,18 @@
#define IS_PAIR(zval) \
EXPECTED(Z_TYPE(zval) == IS_OBJECT) && EXPECTED(Z_OBJCE(zval) == collections_pair_ce)
#define OBJ_PROPERTY_UPDATE(obj, property_name, name_len, value) \
zend_update_property(collections_collection_ce, obj, property_name, name_len, value)
#define OBJ_PROPERTY_FETCH(obj, property_name, name_len) \
zend_read_property(collections_collection_ce, obj, property_name, name_len, 1, &rv)
#define COLLECTION_UPDATE(obj, value) OBJ_PROPERTY_UPDATE(obj, "_a", sizeof "_a" - 1, value)
#define OBJ_PROPERTY_UPDATE(ce, obj, property_name, value) \
zend_update_property(ce, obj, #property_name, sizeof #property_name - 1, value)
#define OBJ_PROPERTY_FETCH(ce, obj, property_name) \
zend_read_property(ce, obj, #property_name, sizeof #property_name - 1, 1, &rv)
#define COLLECTION_UPDATE(obj, value) OBJ_PROPERTY_UPDATE(collections_collection_ce, obj, _, value)
#define COLLECTION_UPDATE_EX(value) COLLECTION_UPDATE(getThis(), value)
#define COLLECTION_FETCH(obj) OBJ_PROPERTY_FETCH(obj, "_a", sizeof "_a" - 1)
#define COLLECTION_FETCH(obj) OBJ_PROPERTY_FETCH(collections_collection_ce, obj, _)
#define COLLECTION_FETCH_EX() COLLECTION_FETCH(getThis())
#define PAIR_UPDATE_FIRST(obj, value) \
OBJ_PROPERTY_UPDATE(obj, "first", sizeof "first" - 1, value)
#define PAIR_UPDATE_SECOND(obj, value) \
OBJ_PROPERTY_UPDATE(obj, "second", sizeof "second" - 1, value)
#define PAIR_FETCH_FIRST(obj) OBJ_PROPERTY_FETCH(obj, "first", sizeof "first" - 1)
#define PAIR_FETCH_SECOND(obj) OBJ_PROPERTY_FETCH(obj, "second", sizeof "second" - 1)
#define PAIR_UPDATE_FIRST(obj, value) OBJ_PROPERTY_UPDATE(collections_pair_ce, obj, first, value)
#define PAIR_UPDATE_SECOND(obj, value) OBJ_PROPERTY_UPDATE(collections_pair_ce, obj, second, value)
#define PAIR_FETCH_FIRST(obj) OBJ_PROPERTY_FETCH(collections_pair_ce, obj, first)
#define PAIR_FETCH_SECOND(obj) OBJ_PROPERTY_FETCH(collections_pair_ce, obj, second)
#define INIT_FCI() \
zval params[2], rv, retval; \
@ -51,6 +49,16 @@
else \
ZVAL_LONG(&params[1], (bucket)->h)
#define INIT_EQUAL_CHECK_FUNC(val) \
int (*equal_check_func)(zval*, zval*); \
if (Z_TYPE_P(element) == IS_LONG) \
equal_check_func = fast_equal_check_long; \
else if (Z_TYPE_P(element) == IS_STRING) \
equal_check_func = fast_equal_check_string; \
else \
equal_check_func = fast_equal_check_function;
#define PHP_COLLECTIONS_ERROR(type, msg) php_error_docref(NULL, type, msg)
#define ERR_BAD_ARGUMENT_TYPE() PHP_COLLECTIONS_ERROR(E_WARNING, "Bad argument type")
#define ERR_BAD_KEY_TYPE() PHP_COLLECTIONS_ERROR(E_WARNING, "Key must be integer or string")
@ -264,12 +272,42 @@ PHP_METHOD(Collection, associateByTo)
PHP_METHOD(Collection, average)
{
zval rv;
zval* current = COLLECTION_FETCH_EX();
double sum = 0;
ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(current), zval* val)
if (Z_TYPE_P(val) == IS_LONG)
sum += Z_LVAL_P(val);
else if (Z_TYPE_P(val) == IS_DOUBLE)
sum += Z_DVAL_P(val);
else {
ERR_BAD_ARGUMENT_TYPE();
RETURN_NULL();
}
ZEND_HASH_FOREACH_END();
RETVAL_DOUBLE(sum / zend_hash_num_elements(Z_ARRVAL_P(current)));
}
PHP_METHOD(Collection, containsAll)
{
zval* elements;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(elements)
ZEND_PARSE_PARAMETERS_END();
ELEMENTS_VALIDATE(elements);
zval rv;
zval* current = COLLECTION_FETCH_EX();
ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(elements), zval* element)
INIT_EQUAL_CHECK_FUNC(element);
int result = 0;
ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(current), zval* val)
if (result = equal_check_func(element, val))
break;
ZEND_HASH_FOREACH_END();
if (result == 0)
RETURN_FALSE;
ZEND_HASH_FOREACH_END();
RETURN_TRUE;
}
PHP_METHOD(Collection, containsKey)

10
tests/007-average.phpt Normal file
View File

@ -0,0 +1,10 @@
--TEST--
Test Collection::average().
--FILE--
<?php
$array = [2.632, 7.871, 9.094, 5.457, 3, 9, 6];
$average = Collection::init($array)->average();
if ($average != array_sum($array) / count($array))
echo 'Collection::average() failed.', PHP_EOL;
?>
--EXPECT--

View File

@ -0,0 +1,11 @@
--TEST--
Test Collection::containsAll().
--FILE--
<?php
$array = [[], 1, 't'];
$array1 = [2, ['t'], 5];
$collection = Collection::init([1, 2, 't', [], 5]);
if (!$collection->containsAll($array) || $collection->containsAll($array1))
echo 'Collection::containsAll() failed.', PHP_EOL;
?>
--EXPECT--