Compare commits
40 Commits
v0.1.0-bet
...
master
Author | SHA1 | Date | |
---|---|---|---|
9a7a72dd29 | |||
66934839e8 | |||
96a7c69edd | |||
f4b5e60ba9 | |||
9cd6222d39 | |||
d7f2835fc0 | |||
eeb0b4e809 | |||
368a49271a | |||
1baf525cd7 | |||
426d80e5b1 | |||
8d9f4d773b | |||
394fdbf5f0 | |||
da855f8844 | |||
5f3f4f1d96 | |||
28c9cbb2f1 | |||
fea371d6b2 | |||
cbc03da7fb | |||
fddc87e95d | |||
14c4c57736 | |||
f00e72f4ac | |||
98b01ef3e2 | |||
cf09a314b2 | |||
e4a0cc2df8 | |||
dfde697222 | |||
f419ce8c2a | |||
db7b116481 | |||
9b8df0bf01 | |||
c480413b1e | |||
60ae083093 | |||
c9f785935a | |||
28e2cef92c | |||
8af47a3960 | |||
e2b2fc0150 | |||
db57bc126d | |||
3245047186 | |||
4eba5b27b7 | |||
1b2d443697 | |||
7c9fda5c64 | |||
693e404667 | |||
d39b273251 |
4
.gitattributes
vendored
4
.gitattributes
vendored
|
@ -1 +1,3 @@
|
||||||
*.h linguist-language=C
|
*.h linguist-language=C
|
||||||
|
stubs/* linguist-documentation
|
||||||
|
config.m4 linguist-detectable=false
|
||||||
|
|
15
.gitignore
vendored
15
.gitignore
vendored
|
@ -28,11 +28,14 @@ missing
|
||||||
mkinstalldirs
|
mkinstalldirs
|
||||||
modules
|
modules
|
||||||
run-tests.php
|
run-tests.php
|
||||||
tests/*/*.diff
|
tests/*.diff
|
||||||
tests/*/*.out
|
tests/*.out
|
||||||
tests/*/*.php
|
tests/*.php
|
||||||
tests/*/*.exp
|
tests/*.exp
|
||||||
tests/*/*.log
|
tests/*.log
|
||||||
tests/*/*.sh
|
tests/*.sh
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
*.gcov
|
||||||
|
*.gcda
|
||||||
|
*.gcno
|
||||||
|
|
14
.travis.yml
14
.travis.yml
|
@ -1,15 +1,19 @@
|
||||||
dist: xenial
|
|
||||||
group: edge
|
|
||||||
|
|
||||||
language: php
|
language: php
|
||||||
|
|
||||||
|
dist: bionic
|
||||||
|
|
||||||
php:
|
php:
|
||||||
- 7.1
|
- 7.1
|
||||||
- 7.2
|
- 7.2
|
||||||
- nightly
|
- 7.3
|
||||||
|
- 7.4
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- phpize
|
- phpize
|
||||||
- ./configure
|
- ./configure
|
||||||
- make
|
- make EXTRA_CFLAGS='-coverage' EXTRA_LDFLAGS='-fprofile-arcs'
|
||||||
- make test
|
- make test
|
||||||
|
- gcov --object-directory=src/.libs src/collections_methods.c
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
4
LICENSE
4
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
The MIT License (MIT)
|
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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
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
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
|
|
101
README.md
101
README.md
|
@ -1,57 +1,33 @@
|
||||||
# ext-collections
|
# ext-collections
|
||||||
|
|
||||||
[![Travis-CI](https://travis-ci.org/CismonX/ext-collections.svg?branch=master)](https://travis-ci.org/CismonX/ext-collections)
|
[![Travis-CI](https://travis-ci.com/CismonX/ext-collections.svg?branch=master)](https://travis-ci.com/CismonX/ext-collections)
|
||||||
[![MIT license](https://img.shields.io/badge/licence-MIT-blue.svg)](https://opensource.org/licenses/MIT)
|
[![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
|
## 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.
|
### 1.1 Example
|
||||||
* Thread safety:
|
|
||||||
* Distinct objects: **safe**.
|
|
||||||
* Shared objects: **unsafe**.
|
|
||||||
|
|
||||||
## 2. Documentation
|
Here is a simple example on how to work with arrays gracefully using this extension.
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$employees = [
|
$employees = [
|
||||||
['name' => 'Alice', 'sex' => 'female', 'age' => 35],
|
['name' => 'Alice', 'gender' => 'female', 'age' => 35],
|
||||||
['name' => 'Bob', 'sex' => 'male', 'age' => 29],
|
['name' => 'Bob', 'gender' => 'male', 'age' => 29],
|
||||||
['name' => 'David', 'sex' => 'male', 'age' => 40],
|
['name' => 'David', 'gender' => 'male', 'age' => 40],
|
||||||
['name' => 'Benjamin', 'sex' => 'male', 'age' => 32]
|
['name' => 'Benjamin', 'gender' => 'male', 'age' => 32]
|
||||||
];
|
];
|
||||||
// Trying to get an array of names of male employees,
|
// Trying to get an array of names of male employees,
|
||||||
// sorted by the descending order of their age.
|
// sorted by the descending order of their age.
|
||||||
$names = Collection::init($employees)
|
$names = Collection::init($employees)
|
||||||
->filter(function ($value) {
|
->filter(function ($value) {
|
||||||
return $value['sex'] == 'male';
|
return $value['gender'] == 'male';
|
||||||
})
|
})
|
||||||
->sortedByDescending(function ($value) {
|
->sortedByDescending(function ($value) {
|
||||||
return $value['age'];
|
return $value['age'];
|
||||||
|
@ -62,3 +38,54 @@ $names = Collection::init($employees)
|
||||||
->toArray();
|
->toArray();
|
||||||
// You got $names == ['David', 'Benjamin', 'Bob'].
|
// 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
2
codecov.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ignore:
|
||||||
|
- "src/collections.c"
|
|
@ -17,6 +17,10 @@
|
||||||
zend_declare_class_constant_long(collections_##cls##_ce, name, sizeof(name) - 1, val)
|
zend_declare_class_constant_long(collections_##cls##_ce, name, sizeof(name) - 1, val)
|
||||||
#define COLLECTIONS_PROP_DECLARE(cls, name, flags) \
|
#define COLLECTIONS_PROP_DECLARE(cls, name, flags) \
|
||||||
zend_declare_property_null(collections_##cls##_ce, name, sizeof(name) - 1, 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;
|
zend_object_handlers collection_handlers;
|
||||||
|
|
||||||
|
@ -41,16 +45,16 @@ static zend_always_inline void collection_ce_init()
|
||||||
2, zend_ce_countable,
|
2, zend_ce_countable,
|
||||||
#endif
|
#endif
|
||||||
zend_ce_arrayaccess);
|
zend_ce_arrayaccess);
|
||||||
memcpy(&collection_handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
COLLECTIONS_HANDLERS_INIT(collection);
|
||||||
collection_handlers.unset_dimension = collection_offset_unset;
|
COLLECTIONS_HANDLER_SET(collection, count_elements);
|
||||||
collection_handlers.unset_property = collection_property_unset;
|
COLLECTIONS_HANDLER_SET(collection, has_dimension);
|
||||||
collection_handlers.write_dimension = collection_offset_set;
|
COLLECTIONS_HANDLER_SET(collection, write_dimension);
|
||||||
collection_handlers.write_property = collection_property_set;
|
COLLECTIONS_HANDLER_SET(collection, read_dimension);
|
||||||
collection_handlers.read_dimension = collection_offset_get;
|
COLLECTIONS_HANDLER_SET(collection, unset_dimension);
|
||||||
collection_handlers.read_property = collection_property_get;
|
COLLECTIONS_HANDLER_SET(collection, has_property);
|
||||||
collection_handlers.has_dimension = collection_offset_exists;
|
COLLECTIONS_HANDLER_SET(collection, write_property);
|
||||||
collection_handlers.has_property = collection_property_exists;
|
COLLECTIONS_HANDLER_SET(collection, read_property);
|
||||||
collection_handlers.count_elements = count_collection;
|
COLLECTIONS_HANDLER_SET(collection, unset_property);
|
||||||
}
|
}
|
||||||
|
|
||||||
static zend_always_inline void pair_ce_init()
|
static zend_always_inline void pair_ce_init()
|
||||||
|
|
|
@ -97,14 +97,34 @@ ZEND_BEGIN_ARG_INFO(copy_of_arginfo, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO(copy_of_range_arginfo, 0)
|
ZEND_BEGIN_ARG_INFO(copy_of_range_arginfo, 0)
|
||||||
ZEND_ARG_TYPE_INFO(0, from_idx, IS_LONG, 0)
|
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_END_ARG_INFO()
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO(fill_arginfo, 0)
|
ZEND_BEGIN_ARG_INFO(fill_arginfo, 0)
|
||||||
ZEND_ARG_INFO(0, element)
|
ZEND_ARG_INFO(0, element)
|
||||||
ZEND_ARG_TYPE_INFO(0, from_index, IS_LONG, 0)
|
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_END_ARG_INFO()
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO(get_arginfo, 0)
|
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_ARG_OBJ_INFO(0, destination, Collection, 0)
|
||||||
ZEND_END_ARG_INFO()
|
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[] = {
|
const zend_function_entry collection_methods[] = {
|
||||||
PHP_ME(Collection, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
|
PHP_ME(Collection, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
|
||||||
PHP_ME(Collection, addAll, elements_arginfo, ZEND_ACC_PUBLIC)
|
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, associateBy, associate_by_arginfo, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Collection, associateByTo, associate_by_to_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, 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, containsAll, other_arginfo, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Collection, containsAllKeys, other_arginfo, ZEND_ACC_PUBLIC)
|
PHP_ME(Collection, containsAllKeys, other_arginfo, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Collection, containsAllValues, 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, toPairs, NULL, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Collection, union, other_arginfo, ZEND_ACC_PUBLIC)
|
PHP_ME(Collection, union, other_arginfo, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Collection, values, NULL, 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
|
PHP_FE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,7 +16,7 @@
|
||||||
extern zend_module_entry collections_module_entry;
|
extern zend_module_entry collections_module_entry;
|
||||||
#define phpext_collections_ptr &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
|
#ifdef PHP_WIN32
|
||||||
#define PHP_COLLECTIONS_API __declspec(dllexport)
|
#define PHP_COLLECTIONS_API __declspec(dllexport)
|
||||||
|
@ -28,6 +28,14 @@ extern zend_module_entry collections_module_entry;
|
||||||
|
|
||||||
#if PHP_VERSION_ID < 70100
|
#if PHP_VERSION_ID < 70100
|
||||||
#error "This extension requires PHP 7.1 and above."
|
#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
|
#endif
|
||||||
|
|
||||||
#define PHP_COLLECTIONS_COMPARE_NATURAL (1 << 0)
|
#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;
|
extern zend_object_handlers collection_handlers;
|
||||||
|
|
||||||
int count_collection(zval* obj, zend_long* count);
|
int collection_count_elements(zval* obj, zend_long* count);
|
||||||
int collection_offset_exists(zval* object, zval* offset, int check_empty);
|
int collection_has_dimension(zval* object, zval* offset, int check_empty);
|
||||||
void collection_offset_set(zval* object, zval* offset, zval* value);
|
void collection_write_dimension(zval* object, zval* offset, zval* value);
|
||||||
zval* collection_offset_get(zval* object, zval* offset, int type, zval* retval);
|
zval* collection_read_dimension(zval* object, zval* offset, int type, zval* rv);
|
||||||
void collection_offset_unset(zval* object, zval* offset);
|
void collection_unset_dimension(zval* object, zval* offset);
|
||||||
int collection_property_exists(zval* object, zval* member, int has_set_exists, void**);
|
int collection_has_property(zval* object, zval* member, int has_set_exists, void**);
|
||||||
void collection_property_set(zval* object, zval* member, zval* value, void**);
|
zobj_write_prop_ret_t collection_write_property(zval* object, zval* member, zval* value, void**);
|
||||||
zval* collection_property_get(zval* object, zval* member, int type, void**, zval* retval);
|
zval* collection_read_property(zval* object, zval* member, int type, void**, zval* rv);
|
||||||
void collection_property_unset(zval* object, zval* member, void**);
|
void collection_unset_property(zval* object, zval* member, void**);
|
||||||
|
|
||||||
extern const zend_function_entry collection_methods[];
|
extern const zend_function_entry collection_methods[];
|
||||||
extern const zend_function_entry pair_methods[];
|
extern const zend_function_entry pair_methods[];
|
||||||
|
|
|
@ -18,6 +18,9 @@ PHP_METHOD(Collection, associateTo);
|
||||||
PHP_METHOD(Collection, associateBy);
|
PHP_METHOD(Collection, associateBy);
|
||||||
PHP_METHOD(Collection, associateByTo);
|
PHP_METHOD(Collection, associateByTo);
|
||||||
PHP_METHOD(Collection, average);
|
PHP_METHOD(Collection, average);
|
||||||
|
PHP_METHOD(Collection, binarySearch);
|
||||||
|
PHP_METHOD(Collection, binarySearchBy);
|
||||||
|
PHP_METHOD(Collection, chunked);
|
||||||
PHP_METHOD(Collection, containsAll);
|
PHP_METHOD(Collection, containsAll);
|
||||||
PHP_METHOD(Collection, containsAllKeys);
|
PHP_METHOD(Collection, containsAllKeys);
|
||||||
PHP_METHOD(Collection, containsAllValues);
|
PHP_METHOD(Collection, containsAllValues);
|
||||||
|
@ -109,6 +112,9 @@ PHP_METHOD(Collection, toCollection);
|
||||||
PHP_METHOD(Collection, toPairs);
|
PHP_METHOD(Collection, toPairs);
|
||||||
PHP_METHOD(Collection, union);
|
PHP_METHOD(Collection, union);
|
||||||
PHP_METHOD(Collection, values);
|
PHP_METHOD(Collection, values);
|
||||||
|
PHP_METHOD(Collection, windowed);
|
||||||
|
PHP_METHOD(Collection, zip);
|
||||||
|
PHP_METHOD(Collection, zipWithNext);
|
||||||
|
|
||||||
PHP_METHOD(Pair, __construct);
|
PHP_METHOD(Pair, __construct);
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,49 @@ class Collection implements ArrayAccess, Countable
|
||||||
*/
|
*/
|
||||||
function average() {}
|
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.
|
* 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.
|
* Returns new collection which is a copy of range of original collection.
|
||||||
*
|
*
|
||||||
* @param int $from_index
|
* @param int $from_index
|
||||||
* @param int $num_elements
|
* @param int $to_index
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
function copyOfRange($from_index, $num_elements) {}
|
function copyOfRange($from_index, $to_index) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of elements in this collection.
|
* Returns the number of elements in this collection.
|
||||||
|
@ -217,10 +260,10 @@ class Collection implements ArrayAccess, Countable
|
||||||
*
|
*
|
||||||
* @param mixed $element
|
* @param mixed $element
|
||||||
* @param int $from_index[optional]
|
* @param int $from_index[optional]
|
||||||
* @param int $num_elements[optional]
|
* @param int $to_index[optional]
|
||||||
* @return void
|
* @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.
|
* Returns a collection containing only elements matching the given predicate.
|
||||||
|
@ -547,38 +590,6 @@ class Collection implements ArrayAccess, Countable
|
||||||
*/
|
*/
|
||||||
function none($predicate) {}
|
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.
|
* Performs the given action on each element and returns the collection itself afterwards.
|
||||||
*
|
*
|
||||||
|
@ -912,4 +923,48 @@ class Collection implements ArrayAccess, Countable
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
function values() {}
|
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) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ $array = [3, 7, 6, 9, 2];
|
||||||
// An associative array, however, Collection::copyOfRange() still works,
|
// An associative array, however, Collection::copyOfRange() still works,
|
||||||
// and string keys will be preserved.
|
// and string keys will be preserved.
|
||||||
$array1 = ['a' => 'b', 'c', 'd' => 'e'];
|
$array1 = ['a' => 'b', 'c', 'd' => 'e'];
|
||||||
$array2 = Collection::init($array)->copyOfRange(2, 4)->toArray();
|
$array2 = Collection::init($array)->copyOfRange(2, 6)->toArray();
|
||||||
$array3 = Collection::init($array1)->copyOfRange(1, 2)->toArray();
|
$array3 = Collection::init($array1)->copyOfRange(1, 3)->toArray();
|
||||||
if ($array2 != array_slice($array, 2, 4) || $array3 != array_slice($array1, 1, 2)) {
|
if ($array2 != array_slice($array, 2, 4) || $array3 != array_slice($array1, 1, 2)) {
|
||||||
echo 'Collection::copyOfRange() failed.', PHP_EOL;
|
echo 'Collection::copyOfRange() failed.', PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ Test Collection::fill().
|
||||||
<?php
|
<?php
|
||||||
$array = ['foo', 'bar' => 'baz', 1, 2, 3];
|
$array = ['foo', 'bar' => 'baz', 1, 2, 3];
|
||||||
$collection = Collection::init($array);
|
$collection = Collection::init($array);
|
||||||
$collection->fill('t', 1, 3);
|
$collection->fill('t', 1, 4);
|
||||||
$array1 = ['foo', 'bar' => 't', 't', 't', 3];
|
$array1 = ['foo', 'bar' => 't', 't', 't', 3];
|
||||||
$collection1 = Collection::init($array);
|
$collection1 = Collection::init($array);
|
||||||
$collection1->fill(0);
|
$collection1->fill(0);
|
||||||
|
|
|
@ -4,7 +4,7 @@ Test Collection::sort(), Collection::sortDescending(), Collection::sorted(), Col
|
||||||
<?php
|
<?php
|
||||||
$array = [];
|
$array = [];
|
||||||
for ($i = 0; $i < 100; ++$i) {
|
for ($i = 0; $i < 100; ++$i) {
|
||||||
$array[] = random_int(-200, 200);
|
$array[] = mt_rand(-200, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
$collection = Collection::init($array);
|
$collection = Collection::init($array);
|
||||||
|
|
|
@ -4,7 +4,7 @@ Test Collection::sortBy(), Collection::sortByDescending(), Collection::sortedBy(
|
||||||
<?php
|
<?php
|
||||||
$array = [];
|
$array = [];
|
||||||
for ($i = 0; $i < 4; ++$i) {
|
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) {
|
$sort_by = function ($value) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ Test Collection::distinct().
|
||||||
<?php
|
<?php
|
||||||
$array = [];
|
$array = [];
|
||||||
for ($i = 0; $i < 100; ++$i) {
|
for ($i = 0; $i < 100; ++$i) {
|
||||||
$array[] = random_int(1, 10);
|
$array[] = mt_rand(1, 10);
|
||||||
}
|
}
|
||||||
$collection = Collection::init($array)->distinct();
|
$collection = Collection::init($array)->distinct();
|
||||||
if ($collection->toArray() != array_values(array_unique($array))) {
|
if ($collection->toArray() != array_values(array_unique($array))) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ Test Collection::distinctBy().
|
||||||
<?php
|
<?php
|
||||||
$array = [];
|
$array = [];
|
||||||
for ($i = 0; $i < 100; ++$i) {
|
for ($i = 0; $i < 100; ++$i) {
|
||||||
$array[] = random_bytes(random_int(1, 10));
|
$array[] = random_bytes(mt_rand(1, 10));
|
||||||
}
|
}
|
||||||
$get_len = function ($value) {
|
$get_len = function ($value) {
|
||||||
return strlen($value);
|
return strlen($value);
|
||||||
|
|
|
@ -4,11 +4,11 @@ Test Collection::union().
|
||||||
<?php
|
<?php
|
||||||
$array = [];
|
$array = [];
|
||||||
for ($i = 0; $i < 50; ++$i) {
|
for ($i = 0; $i < 50; ++$i) {
|
||||||
$array[] = random_int(1, 50);
|
$array[] = mt_rand(1, 50);
|
||||||
}
|
}
|
||||||
$array1 = [];
|
$array1 = [];
|
||||||
for ($i = 0; $i < 50; ++$i) {
|
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)));
|
$union = array_values(array_unique(array_merge($array, $array1)));
|
||||||
$collection = Collection::init($array);
|
$collection = Collection::init($array);
|
||||||
|
|
|
@ -4,7 +4,7 @@ Test Collection::sum() and Collection::sumBy().
|
||||||
<?php
|
<?php
|
||||||
$array = [];
|
$array = [];
|
||||||
for ($i = 0; $i < 50; ++$i) {
|
for ($i = 0; $i < 50; ++$i) {
|
||||||
$array[] = random_int(1, 50);
|
$array[] = mt_rand(1, 50);
|
||||||
}
|
}
|
||||||
$collection = Collection::init($array);
|
$collection = Collection::init($array);
|
||||||
$sum = array_sum($array);
|
$sum = array_sum($array);
|
||||||
|
@ -12,7 +12,7 @@ if ($collection->sum() != $sum) {
|
||||||
echo 'Collection::sum() failed.', PHP_EOL;
|
echo 'Collection::sum() failed.', PHP_EOL;
|
||||||
}
|
}
|
||||||
$array = array_map(function ($value) {
|
$array = array_map(function ($value) {
|
||||||
return [$value, floatval($value / random_int(3, 7))];
|
return [$value, floatval($value / mt_rand(3, 7))];
|
||||||
}, $array);
|
}, $array);
|
||||||
$collection = Collection::init($array);
|
$collection = Collection::init($array);
|
||||||
$sum = array_sum(array_column($array, 1));
|
$sum = array_sum(array_column($array, 1));
|
||||||
|
|
|
@ -4,11 +4,11 @@ Test Collection::intersectValues() and Collection::subtract().
|
||||||
<?php
|
<?php
|
||||||
$array = [];
|
$array = [];
|
||||||
for ($i = 0; $i < 50; ++$i) {
|
for ($i = 0; $i < 50; ++$i) {
|
||||||
$array[] = random_int(1, 50);
|
$array[] = mt_rand(1, 50);
|
||||||
}
|
}
|
||||||
$array1 = [];
|
$array1 = [];
|
||||||
for ($i = 0; $i < 50; ++$i) {
|
for ($i = 0; $i < 50; ++$i) {
|
||||||
$array1[] = random_int(1, 50);
|
$array1[] = mt_rand(1, 50);
|
||||||
}
|
}
|
||||||
$collection = Collection::init($array);
|
$collection = Collection::init($array);
|
||||||
$collection1 = Collection::init($array1);
|
$collection1 = Collection::init($array1);
|
||||||
|
|
|
@ -4,11 +4,11 @@ Test Collection::removeAll() and Collection::retainAll().
|
||||||
<?php
|
<?php
|
||||||
$array = [];
|
$array = [];
|
||||||
for ($i = 0; $i < 50; ++$i) {
|
for ($i = 0; $i < 50; ++$i) {
|
||||||
$array[] = random_int(1, 50);
|
$array[] = mt_rand(1, 50);
|
||||||
}
|
}
|
||||||
$array1 = [];
|
$array1 = [];
|
||||||
for ($i = 0; $i < 50; ++$i) {
|
for ($i = 0; $i < 50; ++$i) {
|
||||||
$array1[] = random_int(1, 50);
|
$array1[] = mt_rand(1, 50);
|
||||||
}
|
}
|
||||||
$collection = Collection::init($array);
|
$collection = Collection::init($array);
|
||||||
|
|
||||||
|
|
27
tests/057-chunked.phpt
Normal file
27
tests/057-chunked.phpt
Normal 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--
|
31
tests/058-binary-search-by.phpt
Normal file
31
tests/058-binary-search-by.phpt
Normal 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
30
tests/059-windowed.phpt
Normal 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--
|
29
tests/060-zip-with-next.phpt
Normal file
29
tests/060-zip-with-next.phpt
Normal 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
20
tests/061-zip.phpt
Normal 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--
|
Reference in New Issue
Block a user