diff --git a/src/iter.php b/src/iter.php index 54bcc7c..863d0d6 100644 --- a/src/iter.php +++ b/src/iter.php @@ -893,6 +893,38 @@ function join(string $separator, iterable $iterable): string { return $str; } +/** + * Splits a string by a separator + * + * Examples: + * + * iter\split(', ', 'a, b, c') + * => iter('a', 'b', 'c') + * + * @param string $separator Separator to use between elements + * @param string $data The string to split + * + * @return iterable + */ +function split(string $separator, string $data): iterable +{ + if (\strlen($separator) === 0) { + throw new \InvalidArgumentException('Separator must be non-empty string'); + } + + return (function() use ($separator, $data) { + $offset = 0; + while ( + $offset < \strlen($data) + && false !== $nextOffset = strpos($data, $separator, $offset) + ) { + yield \substr($data, $offset, $nextOffset - $offset); + $offset = $nextOffset + \strlen($separator); + } + yield \substr($data, $offset); + })(); +} + /** * Returns the number of elements an iterable contains. * diff --git a/test/iterTest.php b/test/iterTest.php index 301aa07..dbe518e 100644 --- a/test/iterTest.php +++ b/test/iterTest.php @@ -434,6 +434,18 @@ public function testJoin() { ); } + public function testSplit() { + $this->assertSame(['a', 'b', 'c'], toArray(split(', ', 'a, b, c'))); + $this->assertSame(['b', 'b', 'b', 'b', 'b', 'b', 'b'], toArray(split('a', 'babababababab'))); + + $this->assertSame(['a', 'b', '', '', 'c'], toArray(split(',', 'a,b,,,c'))); + $this->assertSame(['', '', 'c'], toArray(split(',', ',,c'))); + $this->assertSame(['c', '', ''], toArray(split(',', 'c,,'))); + + $this->expectException(\InvalidArgumentException::class); + split('', 'a'); + } + public function testChunk() { $iterable = new \ArrayIterator( ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5]