collector / collector
A collection library inspired by Laravel Collections, built using generators to preserve memory
Requires
- php: ^5.6 | ^7.0
Requires (Dev)
- phpbench/phpbench: @dev
- phpunit/phpunit: ^5.4
This package is auto-updated.
Last update: 2024-08-12 20:56:05 UTC
README
A collection library, inspired by Laravel, Refactoring to Collections, this tweet and my own need/desire for it. Built using generators to preserve memory when dealing with large data sets.
This was put together in about 2 hours - unit tests ripped straight from Laravel - I'd like to implement as much of the Laravel Collection class as possible in due time.
Create a collection
Use the static helper method collect
to create the collection, valid arguments are any objects implementing
\Iterator
including generators, any callable which can resolve to a generator or an array.
//iterator $collection = Collector::collect(new ArrayIterator([1, 2, 3]); //callable generator $collection = Collector::collect(function () { yield 1; yield 2; yield 3; }); //array $collection = Collector::collect([1, 2, 3]);
You can also use the more explicit static constructors if you wish:
//iterator $collection = Collector::fromIterator(new ArrayIterator([1, 2, 3]); //callable generator $collection = Collector::fromCallable(function () { yield 1; yield 2; yield 3; }); //array $collection = Collector::fromArray([1, 2, 3]);
Operations
Map
use Collector\Collector; $source = function () { yield 1; yield 2; yield 3; }; $collection = Collector::fromCallable($source) ->map(function ($item, $key) { return $item * 2; }); var_dump($collection->asArray()); array(3) { [0] => int(2) [1] => int(4) [2] => int(6) }
Filter
use Collector\Collector; $source = function () { yield 1; yield 2; yield 3; }; $collection = Collector::fromCallable($source) ->filter(function ($item, $key) { return $item >=2; }); var_dump($collection->asArray()); array(2) { [1] => int(2) [2] => int(3) }
Flat Map
use Collector\Collector; $source = function () { yield ['name' => 'Aloo Gobi', 'ingredients' => ['Cauliflower', 'Potato']]; yield ['name' => 'Jelfrezi', 'ingredients' => ['Chicken', 'Tomatoes', 'Chili']]; }; $collection = Collector::fromCallable($source) ->flatMap(function ($item, $key) { return $item['ingredients']; }); var_dump($collection->asArray()); array(5) { [0] => string(11) "Cauliflower" [1] => string(6) "Potato" [2] => string(7) "Chicken" [3] => string(8) "Tomatoes" [4] => string(5) "Chili" }
Each
use Collector\Collector; $source = function () { yield ['name' => 'Aloo Gobi', 'ingredients' => ['Cauliflower', 'Potato']]; yield ['name' => 'Jelfrezi', 'ingredients' => ['Chicken', 'Tomatoes', 'Chili']]; }; $collection = Collector::fromCallable($source) ->each(function ($item, $key) { echo $item['name'] . "\n"; }); //Outputs: Aloo Gobi Jelfrezi
Collapse
use Collector\Collector; $source = function () { yield ['garlic', 'chili', 'ginger', 'coriander']; yield ['onions', 'tomatoes']; }; $collection = Collector::fromCallable($source) ->collapse(); var_dump($collection->asArray()); array(6) { [0] => string(6) "garlic" [1] => string(5) "chili" [2] => string(6) "ginger" [3] => string(9) "coriander" [4] => string(6) "onions" [5] => string(8) "tomatoes" }
Flip
use Collector\Collector; $source = function () { yield 'Aydin'; yield 'Caroline'; }; $collection = Collector::fromCallable($source) ->flip(); var_dump($collection->asArray()); array(2) { 'Aydin' => int(0) 'Caroline' => int(1) }
Key By
use Collector\Collector; $source = function () { yield ['name' => 'Vienna']; yield ['name' => 'Lower Austria']; yield ['name' => 'Styria']; }; $collection = Collector::fromCallable($source) ->keyBy(function ($item, $key) { return $item['name']; }); var_dump($collection->asArray()); array(3) { 'Vienna' => array(1) { 'name' => string(6) "Vienna" } 'Lower Austria' => array(1) { 'name' => string(13) "Lower Austria" } 'Styria' => array(1) { 'name' => string(6) "Styria" } }
Values
use Collector\Collector; $source = function () { yield 5 => 'Vienna'; yield 1 => 'Lower Austria'; yield 9 => 'Styria'; }; $collection = Collector::fromCallable($source) ->values(); var_dump($collection->asArray()); array(3) { [0] => string(6) "Vienna" [1] => string(13) "Lower Austria" [2] => string(6) "Styria" }
Keys
use Collector\Collector; $source = function () { yield 5 => 'Vienna'; yield 1 => 'Lower Austria'; yield 9 => 'Styria'; }; $collection = Collector::fromCallable($source) ->keys(); var_dump($collection->asArray()); array(3) { [0] => int(5) [1] => int(1) [2] => int(9) }
Zip
use Collector\Collector; $countries = function () { yield 'Austria'; yield 'Kyrgyzstan'; yield 'Burkina Faso'; }; $continents = function () { yield 'Europe'; yield 'Asia'; yield 'Africa'; }; $zipped = Collector::fromCallable($countries) ->zip(Collector::fromCallable($continents)); foreach ($zipped as $zipPart) { var_dump($zipPart->asArray()); } array(2) { [0] => string(7) "Austria" [1] => string(6) "Europe" } array(2) { [0] => string(10) "Kyrgyzstan" [1] => string(4) "Asia" } array(2) { [0] => string(12) "Burkina Faso" [1] => string(6) "Africa" }
Unit tests
git clone git@github.com:AydinHassan/collector.git cd collector composer install composer test
Benchmarks
There are some bench marks included showing performance and memory consumption metrics of the collection against native operations.
git clone git@github.com:AydinHassan/collector.git
cd collector
composer install
./vendor/bin/phpbench run benchmarks/LoopOneHundredThousandItems.php --report=default
./vendor/bin/phpbench run benchmarks/MapOneMillionItems.php --report=default
./vendor/bin/phpbench run benchmarks/FilterOneMillionItems.php --report=default