Skip to content

Commit

Permalink
Add LazyCollection@remember method (#30443)
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephSilber authored and taylorotwell committed Oct 31, 2019
1 parent a27fa50 commit 70cb9f3
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/Illuminate/Support/LazyCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,44 @@ public function eager()
return new static($this->all());
}

/**
* Cache values as they're enumerated.
*
* @return static
*/
public function remember()
{
$iterator = $this->getIterator();

$iteratorIndex = 0;

$cache = [];

return new static(function () use ($iterator, &$iteratorIndex, &$cache) {
for ($index = 0; true; $index++) {
if (array_key_exists($index, $cache)) {
yield $cache[$index][0] => $cache[$index][1];

continue;
}

if ($iteratorIndex < $index) {
$iterator->next();

$iteratorIndex++;
}

if (! $iterator->valid()) {
break;
}

$cache[$index] = [$iterator->key(), $iterator->current()];

yield $cache[$index][0] => $cache[$index][1];
}
});
}

/**
* Get the average value of a given key.
*
Expand Down
21 changes: 21 additions & 0 deletions tests/Support/SupportLazyCollectionIsLazyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,27 @@ public function testRejectIsLazy()
});
}

public function testRememberIsLazy()
{
$this->assertDoesNotEnumerate(function ($collection) {
$collection->remember();
});

$this->assertEnumeratesOnce(function ($collection) {
$collection = $collection->remember();

$collection->all();
$collection->all();
});

$this->assertEnumerates(5, function ($collection) {
$collection = $collection->remember();

$collection->take(5)->all();
$collection->take(5)->all();
});
}

public function testReplaceIsLazy()
{
$this->assertDoesNotEnumerate(function ($collection) {
Expand Down
74 changes: 74 additions & 0 deletions tests/Support/SupportLazyCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,80 @@ public function testEager()
$this->assertSame([1, 2, 3, 4, 5], $data->all());
}

public function testRemember()
{
$source = [1, 2, 3, 4];

$collection = LazyCollection::make(function () use (&$source) {
yield from $source;
})->remember();

$this->assertSame([1, 2, 3, 4], $collection->all());

$source = [];

$this->assertSame([1, 2, 3, 4], $collection->all());
}

public function testRememberWithTwoRunners()
{
$source = [1, 2, 3, 4];

$collection = LazyCollection::make(function () use (&$source) {
yield from $source;
})->remember();

$a = $collection->getIterator();
$b = $collection->getIterator();

$this->assertEquals(1, $a->current());
$this->assertEquals(1, $b->current());

$b->next();

$this->assertEquals(1, $a->current());
$this->assertEquals(2, $b->current());

$b->next();

$this->assertEquals(1, $a->current());
$this->assertEquals(3, $b->current());

$a->next();

$this->assertEquals(2, $a->current());
$this->assertEquals(3, $b->current());

$a->next();

$this->assertEquals(3, $a->current());
$this->assertEquals(3, $b->current());

$a->next();

$this->assertEquals(4, $a->current());
$this->assertEquals(3, $b->current());

$b->next();

$this->assertEquals(4, $a->current());
$this->assertEquals(4, $b->current());
}

public function testRememberWithDuplicateKeys()
{
$collection = LazyCollection::make(function () {
yield 'key' => 1;
yield 'key' => 2;
})->remember();

$results = $collection->map(function ($value, $key) {
return [$key, $value];
})->values()->all();

$this->assertSame([['key', 1], ['key', 2]], $results);
}

public function testTapEach()
{
$data = LazyCollection::times(10);
Expand Down

0 comments on commit 70cb9f3

Please sign in to comment.