Skip to content
A collection library inspired by Laravel Collections, built using generators to preserve memory
PHP
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
benchmarks
.gitignore
Collector.php
CollectorTest.php
README.md
composer.json
composer.lock
phpbench.json
phpunit.xml
test.php

README.md

Collector

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
You can’t perform that action at this time.