Skip to content

Instantly share code, notes, and snippets.

@PatchRanger
Last active October 18, 2020 06:47
Show Gist options
  • Save PatchRanger/6854629cff6ac8d123226aef81164c6d to your computer and use it in GitHub Desktop.
Save PatchRanger/6854629cff6ac8d123226aef81164c6d to your computer and use it in GitHub Desktop.
PHP iteratorChunk: alternative to array_chunk for iterators
<?php
$fruits = [
'apple',
'banana',
'cherry',
'damson',
'elderberry'
];
foreach (\App\IteratorHelper::iteratorChunk(new \ArrayIterator($fruits), 2) as $fruitsChunk) {
// Handle batch of items. Chunk is an iterator.
var_dump(iterator_to_array($fruitsChunk));
}
/*
array(2) {
[0]=>
string(5) "apple"
[1]=>
string(6) "banana"
}
array(2) {
[2]=>
string(6) "cherry"
[3]=>
string(6) "damson"
}
array(1) {
[4]=>
string(10) "elderberry"
}
*/
<?php
namespace App;
class IteratorHelper
{
public static function iteratorChunk(\Iterator $i, int $size = 100): \Generator
{
for ($i = static::remaining($i); $i->valid(); $i = static::remaining($i)) {
yield new \LimitIterator($i, 0, $size);
}
}
/**
* Converts iterator (whether started or not) to new (not started) generator.
* It is required because "foreach" uses "rewind" internally - which breaks any started generator.
*
* @link https://stackoverflow.com/a/40352724
*/
public static function remaining(\Iterator $i): \Generator
{
// Check is required as "yield from" will break for closed iterators.
if ($i->valid()) {
yield from $i;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment