Skip to content

Commit

Permalink
Merge pull request #35 from kununu/makeCollectionChunkable
Browse files Browse the repository at this point in the history
Add chunk to collection
  • Loading branch information
tdashton authored Nov 18, 2024
2 parents c89a2ce + 7e50443 commit f41e949
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 0 deletions.
23 changes: 23 additions & 0 deletions docs/collection-interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ This method is defined to be a fluent version of `ArrayIterator::append`. To do
$collection->add($item1)->add($item2);
```

### chunk

```php
/** @return self[]|static[] */
public function chunk(int $size): array
```

This method [mirrors the behavior of `array_chunk`](https://www.php.net/manual/function.array-chunk.php) and returns a zero indexed numeric array of the current collection based on the chunk size provided.

### diff

```php
Expand Down Expand Up @@ -77,6 +86,20 @@ Callable signature:
function(mixed $element, string|float|int|bool|null $elementKey): void;
```

### eachChunk

```php
public function eachChunk(int $size, callable $function): self|static
```

This method chunks the collection using the passed `$size` and executes the given anonymous function with each chunk.

Callable signature:

```php
function(CollectionInterface $collection): void;
```

### empty

```php
Expand Down
8 changes: 8 additions & 0 deletions docs/collection-trait.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ $collection->toArray();

Internally it is call the `ArrayIterator::append` and returning the instance to allow fluent calls.

## chunk

Internally this method chunks the collection (by getting a copy with [getArrayCopy](https://www.php.net/manual/en/arrayiterator.getarraycopy.php) method) with the PHP [array_chunk](https://www.php.net/manual/function.array-chunk.php) function, returning a zero indexed array of collections of the same type as the initial one.

## diff

To check the difference between two collections first it checks that the other collection is of the same type as the current one.
Expand All @@ -117,6 +121,10 @@ Finally, it will return the duplicated collection, optionally calling the `uniqu

Internally, this method will iterate through each item of a collection, optionally rewind it at the end of the iteration, calling the anonymous function for each element.

## eachChunk

Internally, this method calls the [chunk](#chunk) method and then executes the passed anonymous function with each chunk.

## empty

Internally is checking if the `ArrayIterator::count` returns 0
Expand Down
5 changes: 5 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ interface Collection extends FromIterable, ToArray
{
public function add(mixed $value): self|static;

/** @return self[]|static[] */
public function chunk(int $size): array;

public function diff(self $other): self|static;

public function duplicates(bool $strict = true, bool $uniques = false): self|static;

public function each(callable $function, bool $rewind = true): self|static;

public function eachChunk(int $size, callable $function): self|static;

public function empty(): bool;

public function has(mixed $value, bool $strict = true): bool;
Expand Down
22 changes: 22 additions & 0 deletions src/CollectionTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ public function add($value): self|static
return $this;
}

/** @return self[] */
public function chunk(int $size): array
{
if ($size < 1) {
return [$this];
}

return array_map(
static fn(array $chunk) => self::fromIterable($chunk),
array_chunk($this->getArrayCopy(), $size)
);
}

public function diff(Collection $other): self|static
{
if (!$other instanceof static) {
Expand Down Expand Up @@ -84,6 +97,15 @@ public function each(callable $function, bool $rewind = true): self|static
return $this;
}

public function eachChunk(int $size, callable $function): self|static
{
foreach ($this->chunk($size) as $chunk) {
$function($chunk);
}

return $this;
}

public function empty(): bool
{
return 0 === $this->count();
Expand Down
99 changes: 99 additions & 0 deletions tests/CollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,52 @@ public function testReverse(): void
self::assertEquals([5, 4, 3, 2, 1], CollectionStub::fromIterable([1, 2, 3, 4, 5])->reverse()->toArray());
}

#[DataProvider('chunkDataProvider')]
public function testChunk(Collection $collection, int $chunkSize, array $expectedChunks): void
{
self::assertEquals($expectedChunks, $collection->chunk($chunkSize));
}

public static function chunkDataProvider(): array
{
return [
'chunk_size_0' => [
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
0,
[
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
],
],
'chunk_size_2' => [
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
2,
[
CollectionStub::fromIterable([1, 2]),
CollectionStub::fromIterable([3, 4]),
CollectionStub::fromIterable([5]),
],
],
'chunk_size_1' => [
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
1,
[
CollectionStub::fromIterable([1]),
CollectionStub::fromIterable([2]),
CollectionStub::fromIterable([3]),
CollectionStub::fromIterable([4]),
CollectionStub::fromIterable([5]),
],
],
'chunk_size_5' => [
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
5,
[
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
],
],
];
}

public function testDiff(): void
{
$collection1 = CollectionStub::fromIterable([1, 2, 3, 4, 5]);
Expand Down Expand Up @@ -553,6 +599,59 @@ public static function eachDataProvider(): array
];
}

#[DataProvider('chunkEachDataProvider')]
public function testChunkEach(Collection $collection, int $chunkSize, array $expectedChunks): void
{
$i = 0;

$collection->eachChunk(
$chunkSize,
function(CollectionStub $collection) use (&$i, $expectedChunks): void {
self::assertEquals($collection, $expectedChunks[$i++]);
}
);
}

public static function chunkEachDataProvider(): array
{
return [
'chunk_each_size_0' => [
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
0,
[
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
],
],
'chunk_each_size_2' => [
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
2,
[
CollectionStub::fromIterable([1, 2]),
CollectionStub::fromIterable([3, 4]),
CollectionStub::fromIterable([5]),
],
],
'chunk_each_size_1' => [
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
1,
[
CollectionStub::fromIterable([1]),
CollectionStub::fromIterable([2]),
CollectionStub::fromIterable([3]),
CollectionStub::fromIterable([4]),
CollectionStub::fromIterable([5]),
],
],
'chunk_each_size_5' => [
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
5,
[
CollectionStub::fromIterable([1, 2, 3, 4, 5]),
],
],
];
}

#[DataProvider('mapDataProvider')]
public function testMap(bool $rewind, ?array $expectedCurrent, bool $expectException): void
{
Expand Down

0 comments on commit f41e949

Please sign in to comment.