# Splitting and Partitioning

> StringZilla for C#

The iterators are lazy and allocation-free: each is a `ref struct` enumerator yielding zero-copy `ReadOnlySpan<byte>` views, so a `foreach` never touches the heap.
The codepoint and segmentation iterators batch 64 boundaries per native call; the substring and byte-set splits and the match iterators advance one `find` at a time.
Policies are fluent methods on the returned value.

```csharp
foreach (Rune rune in Sz.EnumerateRunes(text)) Use(rune);   // cf. string.EnumerateRunes
foreach (var word in Sz.EnumerateWords(text)) Use(word);    // also Graphemes/Sentences/LineBreaks

foreach (var field in Sz.Split(line, ","u8)) Use(field); // cf. string.Split, but zero-copy
foreach (var part in Sz.RSplit(path, "/"u8).WithMaxSplit(1)) Use(part); // from the end, at most one split
foreach (var token in Sz.SplitAny(text, separators)) Use(token); // split on any byte in a Byteset
foreach (var line in Sz.SplitWhitespaces(text).SkipEmpty()) Use(line); // collapse whitespace runs

foreach (long at in Sz.EnumerateMatches(haystack, "ab"u8)) Use(at); // every offset; .Overlapping() for overlaps
foreach (var m in Sz.EnumerateUncasedMatches(haystack, "ß"u8)) Use(m); // caseless; m.Offset, m.Length

var (before, separator, after) = Sz.Partition(text, "="u8); // split at the first "="
```

`WithMaxSplit(n)` stops after `n` separators: `0` yields the whole text, and a negative `n`, the default, splits at every separator.
An empty separator yields the whole text, a trailing separator leaves a final empty segment unless `.SkipEmpty()`, and an empty needle matches at every offset up to and including the end, or at every codepoint boundary when uncased.

`using StringZilla;`

## SplitEnumerable

Allocation-free `foreach` source over split segments. See Sz.Split.

```csharp
struct SplitEnumerable
```

## Skip*SkipEmpty

Drop zero-length segments.

```csharp
SplitEnumerable SkipSkipEmpty();
```

## KeepSeparator

Keep the separator attached to each segment: the trailing separator when splitting forward, the leading separator when splitting in reverse.

```csharp
SplitEnumerable KeepSeparator();
```

## WithMaxSplit

Stop after _maxSplit_  separators, leaving the rest as one final segment: 0 yields the whole text, and a negative count, the default, splits at every separator.

```csharp
SplitEnumerable WithMaxSplit(long maxSplit);
```

## GetEnumerator

Returns an enumerator over the split segments.

```csharp
SplitEnumerator GetEnumerator();
```

## TokenSplitEnumerable

Allocation-free `foreach` source over separator-token splits. See Sz.SplitWhitespaces.

```csharp
struct TokenSplitEnumerable
```

## WithSeparators

Also yield the separator runs, interleaved with the gaps (lossless reconstruction).

```csharp
TokenSplitEnumerable WithSeparators();
```

## OnlySeparators

Yield only the separator runs.

```csharp
TokenSplitEnumerable OnlySeparators();
```

## GetEnumerator

Returns an enumerator over the separator-token split spans.

```csharp
TokenSplitEnumerator GetEnumerator();
```

