Compare commits

...

40 Commits

Author SHA1 Message Date
CismonX 9a7a72dd29 Update LICENSE 2020-03-30 13:21:48 +08:00
CismonX 66934839e8 Update README.md 2020-03-30 13:08:27 +08:00
CismonX 96a7c69edd Add codecov.yml. Bumping version. 2020-03-30 12:43:03 +08:00
CismonX f4b5e60ba9 Update readme and travis config. 2020-03-30 12:28:12 +08:00
CismonX 9cd6222d39 integrating Codecov 2020-03-24 11:07:16 +08:00
CismonX d7f2835fc0 fix travis configuration 2020-03-20 11:34:55 +08:00
CismonX eeb0b4e809 update .travis.yml 2020-03-20 11:20:08 +08:00
CismonX 368a49271a fix bug. refactor code. 2020-03-20 11:15:54 +08:00
CismonX 1baf525cd7 prepare for 0.1.1 2019-12-10 04:52:49 +08:00
CismonX 426d80e5b1 compatible to PHP 7.4 2019-12-10 04:50:01 +08:00
CismonX 8d9f4d773b small refactor && update documentation 2019-07-25 00:09:02 +08:00
CismonX 394fdbf5f0 Merge pull request #4 from CismonX/dev
merge changes
2019-06-12 11:27:48 +08:00
CismonX da855f8844 refactor 2019-06-12 11:20:37 +08:00
CismonX 5f3f4f1d96 update 2019-06-08 00:18:42 +08:00
CismonX 28c9cbb2f1 Merge pull request #3 from CismonX/dev
0.1.0 ready
2019-01-18 21:50:18 +08:00
CismonX fea371d6b2 Prevent compiler warning for PHP 7.3 and above. 2019-01-18 21:43:49 +08:00
CismonX cbc03da7fb Add `zip()`. 2019-01-18 21:37:42 +08:00
CismonX fddc87e95d Compatible for PHP 7.4 2019-01-18 20:58:05 +08:00
CismonX 14c4c57736 Add PHP 7.3 to travis. 2019-01-18 20:44:05 +08:00
CismonX f00e72f4ac Merge pull request #2 from CismonX/dev
Merge dev into master
2018-11-09 12:04:45 +08:00
CismonX 98b01ef3e2 Implement `zipWithNext()`. 2018-11-09 11:57:37 +08:00
CismonX cf09a314b2 update 2018-11-08 22:49:58 +08:00
CismonX e4a0cc2df8 update stub 2018-10-24 13:37:37 +08:00
CismonX dfde697222 fix bug 2018-10-22 20:25:54 +08:00
CismonX f419ce8c2a Implement `windowed()`. 2018-10-22 20:14:33 +08:00
CismonX db7b116481 Add signature for `windowed()`, `zip()`, `zipWithNext()`. 2018-10-12 14:48:02 +08:00
CismonX 9b8df0bf01 Update stubs for `zip()`. Add stubs for `windowed()`, `zipWithNext()`. 2018-10-11 20:23:27 +08:00
CismonX c480413b1e Merge branch 'master' of https://github.com/CismonX/ext-collections into dev 2018-10-11 18:57:07 +08:00
CismonX 60ae083093 refactor code 2018-10-11 18:53:39 +08:00
CismonX c9f785935a Add stub for `zip()`. 2018-09-20 15:23:17 +08:00
CismonX 28e2cef92c Refactor code. 2018-09-16 16:29:55 +08:00
CismonX 8af47a3960 Fix bug. 2018-09-15 22:42:57 +08:00
CismonX e2b2fc0150 Refactor code. Fix test. 2018-09-15 22:34:25 +08:00
CismonX db57bc126d Refactor code. 2018-09-12 15:32:32 +08:00
CismonX 3245047186 Remove `binarySearchWith()`. Fix bug for `binarySearchBy()`. 2018-09-12 14:39:18 +08:00
CismonX 4eba5b27b7 Refactor code. Add signature for `binarySearchWith()`. 2018-09-12 13:50:26 +08:00
CismonX 1b2d443697 Add `binarySearch()` and `binarySearchBy()`. Refactor code. 2018-09-12 13:42:13 +08:00
CismonX 7c9fda5c64 Add chunked(). 2018-09-11 11:28:45 +08:00
CismonX 693e404667 Update signature for `binarySearch()` and `binarySearchBy()`. 2018-09-09 23:05:00 +08:00
CismonX d39b273251 Add signature for `binarySearch()`, `binarySearchBy()`, `chunked()`. 2018-09-09 22:20:39 +08:00
27 changed files with 885 additions and 400 deletions

4
.gitattributes vendored
View File

@ -1 +1,3 @@
*.h linguist-language=C
*.h linguist-language=C
stubs/* linguist-documentation
config.m4 linguist-detectable=false

15
.gitignore vendored
View File

@ -28,11 +28,14 @@ missing
mkinstalldirs
modules
run-tests.php
tests/*/*.diff
tests/*/*.out
tests/*/*.php
tests/*/*.exp
tests/*/*.log
tests/*/*.sh
tests/*.diff
tests/*.out
tests/*.php
tests/*.exp
tests/*.log
tests/*.sh
.idea/
.vscode/
*.gcov
*.gcda
*.gcno

View File

@ -1,15 +1,19 @@
dist: xenial
group: edge
language: php
dist: bionic
php:
- 7.1
- 7.2
- nightly
- 7.3
- 7.4
script:
- phpize
- ./configure
- make
- make EXTRA_CFLAGS='-coverage' EXTRA_LDFLAGS='-fprofile-arcs'
- make test
- gcov --object-directory=src/.libs src/collections_methods.c
after_success:
- bash <(curl -s https://codecov.io/bash)

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018 CismonX
Copyright (c) 2018-2020 CismonX<admin@cismon.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.

101
README.md
View File

@ -1,57 +1,33 @@
# ext-collections
[![Travis-CI](https://travis-ci.org/CismonX/ext-collections.svg?branch=master)](https://travis-ci.org/CismonX/ext-collections)
[![MIT license](https://img.shields.io/badge/licence-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Travis-CI](https://travis-ci.com/CismonX/ext-collections.svg?branch=master)](https://travis-ci.com/CismonX/ext-collections)
[![Codecov](https://codecov.io/gh/CismonX/ext-collections/branch/master/graphs/badge.svg)](https://codecov.io/gh/CismonX/ext-collections)
[![MIT license](https://img.shields.io/badge/licence-MIT-blue.svg)](LICENSE)
## 1. Introduction
This PHP extension provides a set of useful functional-style operations on PHP arrays, which makes array manipulation simple and scalable.
This PHP extension provides a set of useful and convenient operations on PHP arrays, which makes working with arrays simple and scalable.
Method names and functionalities are inspired by [Kotlin.Collections](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/).
Method names and functionalities are inspired by [Kotlin.Collections](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/), having a slightly different style than that of [Laravel Collections](https://laravel.com/docs/5.8/collections).
### 1.1 Notes
Requires PHP version >= 7.1 and < 8.0 (master branch).
* Requires PHP 7.1 and above.
* Thread safety:
* Distinct objects: **safe**.
* Shared objects: **unsafe**.
### 1.1 Example
## 2. Documentation
### 2.1 Functionalities
See [stubs](stubs/) directory for signature of all classes and methods of this extension, with PHPDoc. They can also serve as IDE helper.
### 2.2 PHP-style access
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 and bracket expression.
* `empty()`, `count()` can be used on instance of `Collection`.
* Elements can be traversed via `foreach()` keyword.
### 2.4 Notes
* The `Collection::xxxTo()` methods will preserve the original key-value pairs of destination `Collection` when keys collide.
* Some methods of `Collection` involves comparing two of its elements, which accepts `$flags` as one of its arguments. When these methods are being invoked, make sure all elements are of the same type (numeric/string/others), otherwise you're likely to get a segfault.
## 3. Example
Here is a simple example for how to work with arrays gracefully using this extension.
Here is a simple example on how to work with arrays gracefully using this extension.
```php
$employees = [
['name' => 'Alice', 'sex' => 'female', 'age' => 35],
['name' => 'Bob', 'sex' => 'male', 'age' => 29],
['name' => 'David', 'sex' => 'male', 'age' => 40],
['name' => 'Benjamin', 'sex' => 'male', 'age' => 32]
['name' => 'Alice', 'gender' => 'female', 'age' => 35],
['name' => 'Bob', 'gender' => 'male', 'age' => 29],
['name' => 'David', 'gender' => 'male', 'age' => 40],
['name' => 'Benjamin', 'gender' => 'male', 'age' => 32]
];
// Trying to get an array of names of male employees,
// sorted by the descending order of their age.
$names = Collection::init($employees)
->filter(function ($value) {
return $value['sex'] == 'male';
return $value['gender'] == 'male';
})
->sortedByDescending(function ($value) {
return $value['age'];
@ -62,3 +38,54 @@ $names = Collection::init($employees)
->toArray();
// You got $names == ['David', 'Benjamin', 'Bob'].
```
## 2. Getting Started
### 2.1 Installation
Like other PHP extensions, ext-collections can be built and installed with a few commands:
```bash
phpize
./configure
make
sudo make install
```
Include it in your PHP configuration file to enable this extension:
```php.ini
extension=collections.so
```
Building on Windows is not as convenient, however, pre-built binaries for Windows are provided in the [releases](https://github.com/CismonX/ext-collections/releases). If you want to build it yourself, follow the [official PHP wiki](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2).
### 2.2 API Reference
See [stubs](stubs/) directory for signatures of all classes and methods of this extension, with PHPDoc. They can also serve as IDE helper.
### 2.3 PHP-style Access
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 or bracket expression.
* `empty()`, `count()` can be used on instance of `Collection`.
* Elements can be traversed via `foreach()` keyword.
## 3. Notes
* The `Collection::xxxTo()` methods will preserve the original key-value pairs of destination `Collection` when keys collide.
* Some methods of `Collection` involves comparing two of its elements, which accepts `$flags` as one of its arguments. When these methods are being invoked, make sure all elements are of the same type (numeric/string/others), otherwise you're likely to get a segfault.
### 3.1 Copy-on-write Mechanism
Class `Collection` does not introduce new data structures internally. Instead, it only holds a pointer to a `zend_array`, and all its methods works directly on top of `zend_array`. Which means conversion between `Collection` and `array` does not involve copying, until write operation is performed on one of the duplicates.
```php
$foo = ['a', 'b']; // arr0: refcount = 1
$bar = Collection::init($foo); // arr0: refcount = 2, no copying of either `zend_array` or its elements
echo $bar->containsValue('a'); // arr0: refcount = 2, read operation, no copying
$bar->shuffle(); // arr0: refcount = 1, arr1: refcount = 1, write operation, `zend_array` is separated
$baz = $bar->toArray(); // arr0: refcount = 1, arr1: refcount = 2, no copying
```

2
codecov.yml Normal file
View File

@ -0,0 +1,2 @@
ignore:
- "src/collections.c"

View File

@ -17,6 +17,10 @@
zend_declare_class_constant_long(collections_##cls##_ce, name, sizeof(name) - 1, val)
#define COLLECTIONS_PROP_DECLARE(cls, name, flags) \
zend_declare_property_null(collections_##cls##_ce, name, sizeof(name) - 1, flags)
#define COLLECTIONS_HANDLERS_INIT(cls) \
memcpy(&cls##_handlers, &std_object_handlers, sizeof(zend_object_handlers))
#define COLLECTIONS_HANDLER_SET(cls, name) \
cls##_handlers.name = cls##_##name
zend_object_handlers collection_handlers;
@ -41,16 +45,16 @@ static zend_always_inline void collection_ce_init()
2, zend_ce_countable,
#endif
zend_ce_arrayaccess);
memcpy(&collection_handlers, &std_object_handlers, sizeof(zend_object_handlers));
collection_handlers.unset_dimension = collection_offset_unset;
collection_handlers.unset_property = collection_property_unset;
collection_handlers.write_dimension = collection_offset_set;
collection_handlers.write_property = collection_property_set;
collection_handlers.read_dimension = collection_offset_get;
collection_handlers.read_property = collection_property_get;
collection_handlers.has_dimension = collection_offset_exists;
collection_handlers.has_property = collection_property_exists;
collection_handlers.count_elements = count_collection;
COLLECTIONS_HANDLERS_INIT(collection);
COLLECTIONS_HANDLER_SET(collection, count_elements);
COLLECTIONS_HANDLER_SET(collection, has_dimension);
COLLECTIONS_HANDLER_SET(collection, write_dimension);
COLLECTIONS_HANDLER_SET(collection, read_dimension);
COLLECTIONS_HANDLER_SET(collection, unset_dimension);
COLLECTIONS_HANDLER_SET(collection, has_property);
COLLECTIONS_HANDLER_SET(collection, write_property);
COLLECTIONS_HANDLER_SET(collection, read_property);
COLLECTIONS_HANDLER_SET(collection, unset_property);
}
static zend_always_inline void pair_ce_init()

View File

@ -97,14 +97,34 @@ ZEND_BEGIN_ARG_INFO(copy_of_arginfo, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(copy_of_range_arginfo, 0)
ZEND_ARG_TYPE_INFO(0, from_idx, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, num_elements, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, from_index, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, to_index, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(fill_arginfo, 0)
ZEND_ARG_INFO(0, element)
ZEND_ARG_TYPE_INFO(0, from_index, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, num_elements, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, to_index, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(binary_search_arginfo, 0)
ZEND_ARG_INFO(0, element)
ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, from_index, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, to_index, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(binary_search_by_arginfo, 0)
ZEND_ARG_INFO(0, element)
ZEND_ARG_CALLABLE_INFO(0, selector, 0)
ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, from_index, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, to_index, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(chuncked_arginfo, 0)
ZEND_ARG_TYPE_INFO(0, size, IS_LONG, 0)
ZEND_ARG_CALLABLE_INFO(0, transform, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(get_arginfo, 0)
@ -116,6 +136,18 @@ ZEND_BEGIN_ARG_INFO(to_collection_arginfo, 0)
ZEND_ARG_OBJ_INFO(0, destination, Collection, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(windowed_arginfo, 0)
ZEND_ARG_TYPE_INFO(0, size, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, step, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, partial_windows, _IS_BOOL, 0)
ZEND_ARG_CALLABLE_INFO(0, transform, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(zip_arginfo, 0)
ZEND_ARG_INFO(0, other)
ZEND_ARG_CALLABLE_INFO(0, transform, 0)
ZEND_END_ARG_INFO()
const zend_function_entry collection_methods[] = {
PHP_ME(Collection, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
PHP_ME(Collection, addAll, elements_arginfo, ZEND_ACC_PUBLIC)
@ -126,6 +158,9 @@ const zend_function_entry collection_methods[] = {
PHP_ME(Collection, associateBy, associate_by_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, associateByTo, associate_by_to_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, average, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Collection, binarySearch, binary_search_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, binarySearchBy, binary_search_by_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, chunked, chuncked_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, containsAll, other_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, containsAllKeys, other_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, containsAllValues, other_arginfo, ZEND_ACC_PUBLIC)
@ -217,6 +252,9 @@ const zend_function_entry collection_methods[] = {
PHP_ME(Collection, toPairs, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Collection, union, other_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, values, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Collection, windowed, windowed_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, zip, zip_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(Collection, zipWithNext, transform_arginfo, ZEND_ACC_PUBLIC)
PHP_FE_END
};

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
extern zend_module_entry collections_module_entry;
#define phpext_collections_ptr &collections_module_entry
#define PHP_COLLECTIONS_VERSION "0.1.0"
#define PHP_COLLECTIONS_VERSION "0.1.2"
#ifdef PHP_WIN32
#define PHP_COLLECTIONS_API __declspec(dllexport)
@ -28,6 +28,14 @@ extern zend_module_entry collections_module_entry;
#if PHP_VERSION_ID < 70100
#error "This extension requires PHP 7.1 and above."
#elif PHP_VERSION_ID >= 80000
#error "This extension does not yet support PHP 8.0 (which is under development)."
#endif
#if PHP_VERSION_ID >= 70400
typedef zval* zobj_write_prop_ret_t;
#else
typedef void zobj_write_prop_ret_t;
#endif
#define PHP_COLLECTIONS_COMPARE_NATURAL (1 << 0)
@ -56,15 +64,15 @@ extern PHP_COLLECTIONS_API zend_class_entry* collections_pair_ce;
extern zend_object_handlers collection_handlers;
int count_collection(zval* obj, zend_long* count);
int collection_offset_exists(zval* object, zval* offset, int check_empty);
void collection_offset_set(zval* object, zval* offset, zval* value);
zval* collection_offset_get(zval* object, zval* offset, int type, zval* retval);
void collection_offset_unset(zval* object, zval* offset);
int collection_property_exists(zval* object, zval* member, int has_set_exists, void**);
void collection_property_set(zval* object, zval* member, zval* value, void**);
zval* collection_property_get(zval* object, zval* member, int type, void**, zval* retval);
void collection_property_unset(zval* object, zval* member, void**);
int collection_count_elements(zval* obj, zend_long* count);
int collection_has_dimension(zval* object, zval* offset, int check_empty);
void collection_write_dimension(zval* object, zval* offset, zval* value);
zval* collection_read_dimension(zval* object, zval* offset, int type, zval* rv);
void collection_unset_dimension(zval* object, zval* offset);
int collection_has_property(zval* object, zval* member, int has_set_exists, void**);
zobj_write_prop_ret_t collection_write_property(zval* object, zval* member, zval* value, void**);
zval* collection_read_property(zval* object, zval* member, int type, void**, zval* rv);
void collection_unset_property(zval* object, zval* member, void**);
extern const zend_function_entry collection_methods[];
extern const zend_function_entry pair_methods[];

View File

@ -18,6 +18,9 @@ PHP_METHOD(Collection, associateTo);
PHP_METHOD(Collection, associateBy);
PHP_METHOD(Collection, associateByTo);
PHP_METHOD(Collection, average);
PHP_METHOD(Collection, binarySearch);
PHP_METHOD(Collection, binarySearchBy);
PHP_METHOD(Collection, chunked);
PHP_METHOD(Collection, containsAll);
PHP_METHOD(Collection, containsAllKeys);
PHP_METHOD(Collection, containsAllValues);
@ -109,6 +112,9 @@ PHP_METHOD(Collection, toCollection);
PHP_METHOD(Collection, toPairs);
PHP_METHOD(Collection, union);
PHP_METHOD(Collection, values);
PHP_METHOD(Collection, windowed);
PHP_METHOD(Collection, zip);
PHP_METHOD(Collection, zipWithNext);
PHP_METHOD(Pair, __construct);

View File

@ -92,6 +92,49 @@ class Collection implements ArrayAccess, Countable
*/
function average() {}
/**
* Searches the array or the range of the array for the provided element using the
* binary search algorithm.
*
* The array is expected to be packed and sorted into ascending order, otherwise the
* result is undefined.
*
* @param mixed $element
* @param int $flags[optional]
* @param int $from_index[optional]
* @param int $to_index[optional]
* @return int|null
*/
function binarySearch($element, $flags, $from_index, $to_index) {}
/**
* Searches the array or the range of the array for the provided element using the
* binary search algorithm, where the element equals to the one returned by the
* corresponding selector function.
*
* The array is expected to be packed and sorted into ascending order, otherwise the
* result is undefined.
*
* @param mixed $element
* @param callable $selector ($value, $key) -> $new_value
* @param int $flags[optional]
* @param int $from_index[optional]
* @param int $to_index[optional]
* @return int|null
*/
function binarySearchBy($element, $selector, $flags, $from_index, $to_index) {}
/**
* Splits this collection into a collection of arrays each not exceeding the given size.
*
* If the transform function is provided, apply it on each array.
*
* @param int $size
* @param callable $transform[optional] ($value, $key) -> $new_value
* @return Collection
*/
function chunked($size, $transform) {}
/**
* Checks if all key-value pairs in the specified collection are contained in this collection.
*
@ -144,10 +187,10 @@ class Collection implements ArrayAccess, Countable
* Returns new collection which is a copy of range of original collection.
*
* @param int $from_index
* @param int $num_elements
* @param int $to_index
* @return Collection
*/
function copyOfRange($from_index, $num_elements) {}
function copyOfRange($from_index, $to_index) {}
/**
* Returns the number of elements in this collection.
@ -217,10 +260,10 @@ class Collection implements ArrayAccess, Countable
*
* @param mixed $element
* @param int $from_index[optional]
* @param int $num_elements[optional]
* @param int $to_index[optional]
* @return void
*/
function fill($element, $from_index, $num_elements) {}
function fill($element, $from_index, $to_index) {}
/**
* Returns a collection containing only elements matching the given predicate.
@ -547,38 +590,6 @@ class Collection implements ArrayAccess, Countable
*/
function none($predicate) {}
/**
* This method is implemented in handlers.unset_dimension.
* There's no method with name 'offsetUnset'.
*
* @internal
*/
function offsetUnset($key) {}
/**
* This method is implemented in handlers.write_dimension.
* There's no method with name 'offsetSet'.
*
* @internal
*/
function offsetSet($key, $value) {}
/**
* This method is implemented in handlers.read_dimension.
* There's no method with name 'offsetGet'.
*
* @internal
*/
function offsetGet($key) {}
/**
* This method is implemented in handlers.has_dimension.
* There's no method with name 'offsetExists'.
*
* @internal
*/
function offsetExists($key) {}
/**
* Performs the given action on each element and returns the collection itself afterwards.
*
@ -912,4 +923,48 @@ class Collection implements ArrayAccess, Countable
* @return Collection
*/
function values() {}
/**
* Returns a collection of snapshots of the window of the given size sliding along this
* collection with the given step, where each snapshot is an array.
*
* If provided, the transform function will be applied to each snapshot.
*
* The wrapped array must be packed.
*
* @param int $size
* @param int $step[optional] = 1
* @param bool $partial_windows[optional] = false
* @param callable $transform[optional] ($value, $key) -> $new_value
* @return Collection
*/
function windowed($size, $step, $partial_windows, $transform) {}
/**
* Returns a collection of pairs built from the elements of this array and other array
* with the same index. The returned collection has length of the shortest array.
*
* If the transform function is provided, return a collection of the return values of
* the transform function applied to each pair of elements.
*
* Both arrays must be packed.
*
* @param array|Collection $other
* @param callable $transform[optional] ($v1, $v2) -> $new_value
* @return Collection
*/
function zip($other, $transform) {}
/**
* Returns a list of pairs of each two adjacent elements in this collection.
*
* If the transform function is provided, return a collection of the return values of
* the transform function applied to each pair of elements.
*
* The wrapped array must be packed.
*
* @param callable $transform[optional] ($v1, $v2) -> $new_value
* @return Collection
*/
function zipWithNext($transform) {}
}

View File

@ -7,8 +7,8 @@ $array = [3, 7, 6, 9, 2];
// An associative array, however, Collection::copyOfRange() still works,
// and string keys will be preserved.
$array1 = ['a' => 'b', 'c', 'd' => 'e'];
$array2 = Collection::init($array)->copyOfRange(2, 4)->toArray();
$array3 = Collection::init($array1)->copyOfRange(1, 2)->toArray();
$array2 = Collection::init($array)->copyOfRange(2, 6)->toArray();
$array3 = Collection::init($array1)->copyOfRange(1, 3)->toArray();
if ($array2 != array_slice($array, 2, 4) || $array3 != array_slice($array1, 1, 2)) {
echo 'Collection::copyOfRange() failed.', PHP_EOL;
}

View File

@ -4,7 +4,7 @@ Test Collection::fill().
<?php
$array = ['foo', 'bar' => 'baz', 1, 2, 3];
$collection = Collection::init($array);
$collection->fill('t', 1, 3);
$collection->fill('t', 1, 4);
$array1 = ['foo', 'bar' => 't', 't', 't', 3];
$collection1 = Collection::init($array);
$collection1->fill(0);

View File

@ -4,7 +4,7 @@ Test Collection::sort(), Collection::sortDescending(), Collection::sorted(), Col
<?php
$array = [];
for ($i = 0; $i < 100; ++$i) {
$array[] = random_int(-200, 200);
$array[] = mt_rand(-200, 200);
}
$collection = Collection::init($array);

View File

@ -4,7 +4,7 @@ Test Collection::sortBy(), Collection::sortByDescending(), Collection::sortedBy(
<?php
$array = [];
for ($i = 0; $i < 4; ++$i) {
$array[random_bytes(2)] = [random_int(10, 99)];
$array[random_bytes(2)] = [mt_rand(10, 99)];
}
$sort_by = function ($value) {

View File

@ -4,7 +4,7 @@ Test Collection::distinct().
<?php
$array = [];
for ($i = 0; $i < 100; ++$i) {
$array[] = random_int(1, 10);
$array[] = mt_rand(1, 10);
}
$collection = Collection::init($array)->distinct();
if ($collection->toArray() != array_values(array_unique($array))) {

View File

@ -4,7 +4,7 @@ Test Collection::distinctBy().
<?php
$array = [];
for ($i = 0; $i < 100; ++$i) {
$array[] = random_bytes(random_int(1, 10));
$array[] = random_bytes(mt_rand(1, 10));
}
$get_len = function ($value) {
return strlen($value);

View File

@ -4,11 +4,11 @@ Test Collection::union().
<?php
$array = [];
for ($i = 0; $i < 50; ++$i) {
$array[] = random_int(1, 50);
$array[] = mt_rand(1, 50);
}
$array1 = [];
for ($i = 0; $i < 50; ++$i) {
$array1[] = random_int(1, 50);
$array1[] = mt_rand(1, 50);
}
$union = array_values(array_unique(array_merge($array, $array1)));
$collection = Collection::init($array);

View File

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

View File

@ -4,11 +4,11 @@ Test Collection::intersectValues() and Collection::subtract().
<?php
$array = [];
for ($i = 0; $i < 50; ++$i) {
$array[] = random_int(1, 50);
$array[] = mt_rand(1, 50);
}
$array1 = [];
for ($i = 0; $i < 50; ++$i) {
$array1[] = random_int(1, 50);
$array1[] = mt_rand(1, 50);
}
$collection = Collection::init($array);
$collection1 = Collection::init($array1);

View File

@ -4,11 +4,11 @@ Test Collection::removeAll() and Collection::retainAll().
<?php
$array = [];
for ($i = 0; $i < 50; ++$i) {
$array[] = random_int(1, 50);
$array[] = mt_rand(1, 50);
}
$array1 = [];
for ($i = 0; $i < 50; ++$i) {
$array1[] = random_int(1, 50);
$array1[] = mt_rand(1, 50);
}
$collection = Collection::init($array);

27
tests/057-chunked.phpt Normal file
View File

@ -0,0 +1,27 @@
--TEST--
Test Collection::chunked().
--FILE--
<?php
$array = [];
$size = mt_rand(20, 30);
for ($i = 0; $i < 50; ++$i) {
$array[] = mt_rand(100, 200);
}
$chunk_size = mt_rand(4, 9);
$chunked = array_chunk($array, $chunk_size, false);
$collection = Collection::init($array);
if ($collection->chunked($chunk_size)->toArray() != $chunked) {
echo 'Collection::chunked() failed.', PHP_EOL;
}
$transform = function ($value) use ($chunk_size) {
if (count($value) < $chunk_size) {
return [];
}
return $value;
};
$chunked = array_map($transform, $chunked);
if ($collection->chunked($chunk_size, $transform)->toArray() != $chunked) {
echo 'Collection::chunked() failed.', PHP_EOL;
}
?>
--EXPECT--

View File

@ -0,0 +1,31 @@
--TEST--
Test Collection::binarySearch() and Collection::binarySearchBy().
--FILE--
<?php
$array = [];
$size = mt_rand(20, 30);
for ($i = 0; $i < 50; ++$i) {
$array[] = mt_rand(100, 200);
}
$array = array_unique($array);
sort($array);
$idx = mt_rand(0, count($array) - 1);
$which = $array[$idx];
$from = mt_rand(0, $idx);
$to = mt_rand($idx + 1, count($array));
$collection = Collection::init($array);
if ($collection->binarySearch($which, 0, $from, $to) != $idx) {
echo 'Collection::binarySearch() failed.', PHP_EOL;
}
$array = array_map(function ($value) {
return [$value];
}, $array);
$selector = function ($value) {
return $value[0];
};
$collection = Collection::init($array);
if ($collection->binarySearchBy($which, $selector, 0, $from, $to) != $idx) {
echo 'Collection::binarySearchBy() failed.', PHP_EOL;
}
?>
--EXPECT--

30
tests/059-windowed.phpt Normal file
View File

@ -0,0 +1,30 @@
--TEST--
Test Collection::windowed().
--FILE--
<?php
$array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
$collection = Collection::init($array);
$array1 = [
['a', 'b', 'c'],
['c', 'd', 'e'],
['e', 'f', 'g']
];
if ($collection->windowed(3, 2, false)->toArray() != $array1) {
echo 'Collection::windowed() failed.', PHP_EOL;
}
$array1 = [
['a', 'b', 'c', 'd', 4],
['d', 'e', 'f', 'g', 4],
['g', 'h', 2]
];
$transform = function ($snapshot) {
$snapshot[] = count($snapshot);
return $snapshot;
};
if ($collection->windowed(4, 3, true, $transform)->toArray() != $array1) {
echo 'Collection::windowed() failed.', PHP_EOL;
}
?>
--EXPECT--

View File

@ -0,0 +1,29 @@
--TEST--
Test Collection::zipWithNext().
--FILE--
<?php
$array = ['foo'];
if (Collection::init($array)->zipWithNext()->toArray() != []) {
echo 'Collection::zipWithNext() failed.', PHP_EOL;
}
$array = ['a', 'b', 'c', 'd'];
$collection = Collection::init($array);
$array1 = [
new Pair('a', 'b'),
new Pair('b', 'c'),
new Pair('c', 'd')
];
if ($collection->zipWithNext()->toArray() != $array1) {
echo 'Collection::zipWithNext() failed.', PHP_EOL;
}
$transform = function ($v1, $v2) {
return $v1.$v2;
};
$array1 = ['ab', 'bc', 'cd'];
if ($collection->zipWithNext($transform)->toArray() != $array1) {
echo 'Collection::zipWithNext() failed.', PHP_EOL;
}
?>
--EXPECT--

20
tests/061-zip.phpt Normal file
View File

@ -0,0 +1,20 @@
--TEST--
Test Collection::zip().
--FILE--
<?php
$array = ['a', 'b', 'c'];
$array1 = ['d', 'e'];
$zipped = Collection::init($array)->zip($array1)->toArray();
if ($zipped != [new Pair('a', 'd'), new Pair('b', 'e')]) {
echo 'Collection::zip() failed.', PHP_EOL;
}
$transform = function ($v1, $v2) {
return $v1.$v2;
};
$zipped = Collection::init($array1)->zip($array, $transform)->toArray();
if ($zipped != ['da', 'eb']) {
echo 'Collection::zip() failed.', PHP_EOL;
}
?>
--EXPECT--