# Splitting and Partitioning

> StringZilla for Python

### Eager Splits Returning `Strings`

- `split(separator, maxsplit=∞, keepseparator=False, skip_empty=False)` — split on a substring separator; unlike `str.split`, an empty separator leaves the text whole instead of raising.
- `rsplit(separator, maxsplit=∞, keepseparator=False, skip_empty=False)` — same, scanning from the right.
- `split_byteset(separators, maxsplit=∞, keepseparator=False, skip_empty=False)` — split on any single byte from the `separators` set.
- `rsplit_byteset(separators, maxsplit=∞, keepseparator=False, skip_empty=False)` — same, from the right.
- `splitlines(keeplinebreaks=False, maxsplit=∞)` — split on line breaks.

`maxsplit` caps the number of separators consumed, so `0` leaves the text whole, while a negative value or the default means unlimited.
`keepseparator` keeps the matched separator attached to the parts.
`skip_empty` drops zero-length parts, so a part keeping its separator is never dropped.
Without `maxsplit` and `keepseparator`, a one-byte separator, a byteset, and `splitlines` split the whole text in one native pass straight into the tape.

```python
import stringzilla as sz

assert list(map(str, sz.String("a,b,c").split(","))) == ["a", "b", "c"]
assert list(map(str, sz.String("a,b,c").rsplit(",", maxsplit=1))) == ["a,b", "c"]
assert list(map(str, sz.String("a,b;c").split_byteset(",;"))) == ["a", "b", "c"]
assert list(map(str, sz.String("a\nb\nc").splitlines())) == ["a", "b", "c"]
```

### Lazy Split Iterators

Each eager split has a lazy counterpart that yields `String` views one at a time without building the whole `Strings`.
They take the same arguments.

- `split_iter(separator, maxsplit=∞, keepseparator=False, skip_empty=False)`
- `rsplit_iter(separator, maxsplit=∞, keepseparator=False, skip_empty=False)`
- `split_byteset_iter(separators, maxsplit=∞, keepseparator=False, skip_empty=False)`
- `rsplit_byteset_iter(separators, maxsplit=∞, keepseparator=False, skip_empty=False)`

The reverse iterators yield the last field first.

```python
import stringzilla as sz

for field in sz.String("2024-01-15").split_iter("-"):
    print(field)                                       # 2024, then 01, then 15

assert str(next(iter(sz.String("a/b/c").rsplit_iter("/")))) == "c"
assert sum(1 for _ in sz.String("a,b,c").split_iter(",")) == 3
```

### Joining

`join(strings)` concatenates `strings` with the `String` between every two, as `str.join` does, into a new `String`.
A `Strings` is read in place, any other iterable of `str` and bytes-like objects through a snapshot of it, and the result is measured first and written once.

```python
import stringzilla as sz

assert str(sz.String(", ").join(["Ada", "Grace", "Linus"])) == "Ada, Grace, Linus"
assert str(sz.String("\n").join(sz.String("a b c").split())) == "a\nb\nc"
```

### Partitioning

- `partition(separator)` — return a 3-tuple `(head, separator, tail)` split at the first occurrence; if not found returns `(self, '', '')`.
- `rpartition(separator)` — same, at the last occurrence; if not found returns `('', '', self)`.

```python
import stringzilla as sz

assert tuple(map(str, sz.String("a=b=c").partition("="))) == ("a", "=", "b=c")
assert tuple(map(str, sz.String("a=b=c").rpartition("="))) == ("a=b", "=", "c")
```

`import stringzilla`

## FindSplits

Text-splitting iterator for efficient string processing.

```python
class FindSplits
```

Provides lazy evaluation of string splits without materializing all results.

Created by: - String.split_iter()

- String.rsplit_iter()

- String.split_byteset_iter()

- String.rsplit_byteset_iter()

Features: - Memory-efficient: yields results one at a time

- Forward and reverse iteration support

- Character set and string separator support

Examples: ```
>>> # split_iter streams parts lazily - prefer it over split() on large inputs:
>>> for field in sz.String('2024-01-15').split_iter('-'):
...     print(field)
2024
01
15
```

## partition

Split the string into a 3-tuple around the first occurrence of a separator.

```python
def partition(
    text: _StringLike,
    separator: _StringLike,
    *,
    capabilities: Capability | None = None,
) -> tuple[String, String, String]
```

Returns:
tuple: A 3-tuple (head, separator, tail), or `(self, '', '')` if the separator is not found.

- `text`: The string object.
- `separator`: The separator to partition by.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> tuple(map(str, sz.String('a=b=c').partition('=')))
('a', '=', 'b=c')
```

## rpartition

Split the string into a 3-tuple around the last occurrence of a separator.

```python
def rpartition(
    text: _StringLike,
    separator: _StringLike,
    *,
    capabilities: Capability | None = None,
) -> tuple[String, String, String]
```

Returns:
tuple: A 3-tuple (head, separator, tail). If the separator is not found, returns ('', '', self).

- `text`: The string object.
- `separator`: The separator to partition by.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> tuple(map(str, sz.String('a=b=c').rpartition('=')))
('a=b', '=', 'c')
```

## split

Split a string by a separator, like [`str.split`](#split).

```python
def split(
    text: _StringLike,
    separator: _StringLike,
    maxsplit: int = -1,
    keepseparator: bool = False,
    skip_empty: bool = False,
    *,
    capabilities: Capability | None = None,
) -> Strings
```

Returns:
Strings: The parts, copied onto a tape of their own.

- `text`: The string object.
- `separator`: The separator to split by; an empty one leaves the text whole.
- `maxsplit`: Maximum number of splits, defaulting to no limit.
- `keepseparator`: Include the separator in results, defaulting to False.
- `skip_empty`: Skip empty segments, defaulting to False.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> list(map(str, sz.String('a,b,c').split(',')))
['a', 'b', 'c']
```

## rsplit

Split a string by a separator starting from the end, like [`str.rsplit`](#rsplit).

```python
def rsplit(
    text: _StringLike,
    separator: _StringLike,
    maxsplit: int = -1,
    keepseparator: bool = False,
    skip_empty: bool = False,
    *,
    capabilities: Capability | None = None,
) -> Strings
```

Returns:
Strings: The parts, copied onto a tape of their own.

- `text`: The string object.
- `separator`: The separator to split by; an empty one leaves the text whole.
- `maxsplit`: Maximum number of splits, defaulting to no limit.
- `keepseparator`: Include the separator in results, defaulting to False.
- `skip_empty`: Skip empty segments, defaulting to False.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> list(map(str, sz.String('a,b,c').rsplit(',')))
['a', 'b', 'c']
```

## split_byteset

Split a string by a set of character separators.

```python
def split_byteset(
    text: _StringLike,
    separators: _StringLike,
    maxsplit: int = -1,
    keepseparator: bool = False,
    skip_empty: bool = False,
    *,
    capabilities: Capability | None = None,
) -> Strings
```

Returns:
Strings: The parts, copied onto a tape of their own.

- `text`: The string object.
- `separators`: A string containing separator characters.
- `maxsplit`: Maximum number of splits, defaulting to no limit.
- `keepseparator`: Include separators in results, defaulting to False.
- `skip_empty`: Skip empty segments, defaulting to False.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> list(map(str, sz.String('a,b;c').split_byteset(',;')))
['a', 'b', 'c']
```

## rsplit_byteset

Split a string by a set of character separators in reverse order.

```python
def rsplit_byteset(
    text: _StringLike,
    separators: _StringLike,
    maxsplit: int = -1,
    keepseparator: bool = False,
    skip_empty: bool = False,
    *,
    capabilities: Capability | None = None,
) -> Strings
```

Returns:
Strings: The parts, copied onto a tape of their own.

- `text`: The string object.
- `separators`: A string containing separator characters.
- `maxsplit`: Maximum number of splits, defaulting to no limit.
- `keepseparator`: Include separators in results, defaulting to False.
- `skip_empty`: Skip empty segments, defaulting to False.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> list(map(str, sz.String('a,b;c').rsplit_byteset(',;')))
['a', 'b', 'c']
```

## split_iter

Create an iterator for splitting a string by a separator.

```python
def split_iter(
    text: _StringLike,
    separator: _StringLike,
    maxsplit: int = -1,
    keepseparator: bool = False,
    skip_empty: bool = False,
    *,
    capabilities: Capability | None = None,
) -> FindSplits
```

Returns:
iterator: An iterator yielding split substrings.

- `text`: The string object.
- `separator`: The separator to split by; an empty one leaves the text whole.
- `maxsplit`: Maximum number of splits, defaulting to no limit.
- `keepseparator`: Include separator in results, defaulting to False.
- `skip_empty`: Skip empty segments, defaulting to False.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> # Stream parts lazily instead of materializing a list (that is what split() is for):
>>> sum(1 for _ in sz.String('a,b,c').split_iter(','))
3
```

## rsplit_iter

Create an iterator for splitting a string by a separator in reverse order.

```python
def rsplit_iter(
    text: _StringLike,
    separator: _StringLike,
    maxsplit: int = -1,
    keepseparator: bool = False,
    skip_empty: bool = False,
    *,
    capabilities: Capability | None = None,
) -> FindSplits
```

Returns:
iterator: An iterator yielding split substrings in reverse.

- `text`: The string object.
- `separator`: The separator to split by; an empty one leaves the text whole.
- `maxsplit`: Maximum number of splits, defaulting to no limit.
- `keepseparator`: Include separator in results, defaulting to False.
- `skip_empty`: Skip empty segments, defaulting to False.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> # Iterates from the end; the first yielded part is the last field:
>>> str(next(iter(sz.String('a/b/c').rsplit_iter('/'))))
'c'
```

## split_byteset_iter

Create an iterator for splitting a string by a set of character separators.

```python
def split_byteset_iter(
    text: _StringLike,
    separators: _StringLike,
    maxsplit: int = -1,
    keepseparator: bool = False,
    skip_empty: bool = False,
    *,
    capabilities: Capability | None = None,
) -> FindSplits
```

Returns:
iterator: An iterator yielding split substrings.

- `text`: The string object.
- `separators`: A string containing separator characters.
- `maxsplit`: Maximum number of splits, defaulting to no limit.
- `keepseparator`: Include separators in results, defaulting to False.
- `skip_empty`: Skip empty segments, defaulting to False.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> # Splits on ANY byte in the set, streamed lazily:
>>> str(next(iter(sz.String('a,b;c').split_byteset_iter(',;'))))
'a'
```

## rsplit_byteset_iter

Create an iterator for splitting a string by a set of character separators in reverse order.

```python
def rsplit_byteset_iter(
    text: _StringLike,
    separators: _StringLike,
    maxsplit: int = -1,
    keepseparator: bool = False,
    skip_empty: bool = False,
    *,
    capabilities: Capability | None = None,
) -> FindSplits
```

Returns:
iterator: An iterator yielding split substrings in reverse.

- `text`: The string object.
- `separators`: A string containing separator characters.
- `maxsplit`: Maximum number of splits, defaulting to no limit.
- `keepseparator`: Include separators in results, defaulting to False.
- `skip_empty`: Skip empty segments, defaulting to False.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> # Reverse byteset split; first yielded part is the last field:
>>> str(next(iter(sz.String('a,b;c').rsplit_byteset_iter(',;'))))
'c'
```

## splitlines

Split a string by line breaks, like [`str.splitlines`](#splitlines).

```python
def splitlines(
    text: _StringLike,
    keeplinebreaks: bool = False,
    maxsplit: int = -1,
    *,
    capabilities: Capability | None = None,
) -> Strings
```

Returns:
Strings: The lines, copied onto a tape of their own.

- `text`: The string object.
- `keeplinebreaks`: Include line breaks in the results, defaulting to False.
- `maxsplit`: Maximum number of splits, defaulting to no limit.
- `capabilities`: Capabilities to run, defaulting to the CPU's enabled ones.

Examples: ```
>>> list(map(str, sz.String('a\nb\nc').splitlines()))
['a', 'b', 'c']
```

