diff --git a/CHANGELOG.md b/CHANGELOG.md index ceccc18..9bdaac1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 5.9.0 - 2024-07-05 + +### Added + +- `Innmind\Immutable\Sequence::chunk()` + ## 5.8.0 - 2024-06-27 ### Added diff --git a/docs/structures/sequence.md b/docs/structures/sequence.md index daac35c..cfb799e 100644 --- a/docs/structures/sequence.md +++ b/docs/structures/sequence.md @@ -271,6 +271,30 @@ $lines; // ['foo', 'bar', 'baz', ''] !!! note "" The `flatMap` is here in case there is only one chunk in the sequence, in which case the `aggregate` is not called +### `->chunk()` + +This is a shortcut over [`aggregate`](#-aggregate). The same example can be shortened: + +```php +// let's pretend this comes from a stream +$chunks = ['fo', "o\n", 'ba', "r\n", 'ba', "z\n"]; +$lines = Sequence::of(...$chunks) + ->map(Str::of(...)) + ->map( + static fn($chunk) => $chunk + ->toEncoding(Str\Encoding::ascii) + ->split(), + ) + ->chunk(4) + ->map(static fn($chars) => $chars->dropEnd(1)) // to remove "\n" + ->map(Str::of('')->join(...)) + ->map(static fn($line) => $line->toString()) + ->toList(); +$lines; // ['foo', 'bar', 'baz', ''] +``` + +This better accomodates to the case where the initial `Sequence` only contains a single value. + ### `->indices()` Create a new sequence of integers representing the indices of the original sequence. diff --git a/proofs/sequence.php b/proofs/sequence.php index 3e6aab1..606515f 100644 --- a/proofs/sequence.php +++ b/proofs/sequence.php @@ -1,7 +1,11 @@ split() + ->chunk($chunk); + + $chunks->foreach( + static fn($chars) => $assert + ->number($chars->size()) + ->lessThanOrEqual($chunk), + ); + $chunks + ->dropEnd(1) + ->foreach( + static fn($chars) => $assert->same( + $chunk, + $chars->size(), + ), + ); + + $assert->same( + $string, + $chunks + ->flatMap(static fn($chars) => $chars) + ->fold(new Concat) + ->toString(), + ); + }, + ); }; diff --git a/src/Sequence.php b/src/Sequence.php index e5c92b1..61f244d 100644 --- a/src/Sequence.php +++ b/src/Sequence.php @@ -743,6 +743,21 @@ public function aggregate(callable $map): self return new self($this->implementation->aggregate($map, $exfiltrate)); } + /** + * @param positive-int $size + * + * @return self> + */ + public function chunk(int $size): self + { + return $this + ->map(static fn($value) => self::of($value)) + ->aggregate(static fn(Sequence $a, $b) => match ($a->size()) { + $size => self::of($a, $b), + default => self::of($a->append($b)), + }); + } + /** * Force to load all values into memory (only useful for deferred and lazy Sequence) *