std.algorithm.iteration.splitter
- multiple declarations
Function splitter
Lazily splits a range using an element or range as a separator. Separator ranges can be any narrow string type or sliceable range type.
auto splitter(alias pred, Flag!("keepSeparators") keepSeparators = No .keepSeparators, Range, Separator)
(
Range r,
Separator s
)
if (is(typeof(binaryFun!pred(r .front, s)) : bool) && (hasSlicing!Range && hasLength!Range || isNarrowString!Range));
auto splitter(alias pred, Flag!("keepSeparators") keepSeparators = No .keepSeparators, Range, Separator)
(
Range r,
Separator s
)
if (is(typeof(binaryFun!pred(r .front, s .front)) : bool) && (hasSlicing!Range || isNarrowString!Range) && isForwardRange!Separator && (hasLength!Separator || isNarrowString!Separator));
auto splitter(alias isTerminator, Range)
(
Range r
)
if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(r .front))));
Two adjacent separators are considered to surround an empty element in
the split range. Use filter!(a => !a
on the result to compress
empty elements.
The predicate is passed to binaryFun
and accepts
any callable function that can be executed via pred(element, s)
.
Notes
If splitting a string on whitespace and token compression is desired,
consider using splitter
without specifying a separator.
If no separator is passed, the
predicate isTerminator
decides whether to accept an element of r
.
Parameters
Name | Description |
---|---|
pred | The predicate for comparing each element with the separator,
defaulting to "a == b" . |
r | The input range to be
split. Must support slicing and or be a narrow string type. |
s | The element (or range) to be treated as the separator between range segments to be split. |
isTerminator | The predicate for deciding where to split the range when no separator is passed |
keepSeparators | The flag for deciding if the separators are kept |
Constraints
The predicate pred
needs to accept an element of r
and the
separator s
.
Returns
An input range of the subranges of elements between separators. If r
is a forward range
or bidirectional range,
the returned range will be likewise.
When a range is used a separator, bidirectionality isn't possible.
If keepSeparators is equal to Yes.keepSeparators the output will also contain the separators.
If an empty range is given, the result is an empty range. If a range with one separator is given, the result is a range with two empty elements.
See Also
splitter
for a version that splits using a regular expression defined separator,
split
for a version that splits eagerly and
splitWhen
, which compares adjacent elements instead of element against separator.
Example
Basic splitting with characters and numbers.
import std .algorithm .comparison : equal;
assert("a|bc|def" .splitter('|') .equal([ "a", "bc", "def" ]));
int[] a = [1, 0, 2, 3, 0, 4, 5, 6];
int[][] w = [ [1], [2, 3], [4, 5, 6] ];
assert(a .splitter(0) .equal(w));
Example
Basic splitting with characters and numbers and keeping sentinels.
import std .algorithm .comparison : equal;
import std .typecons : Yes;
assert("a|bc|def" .splitter!("a == b", Yes .keepSeparators)('|')
.equal([ "a", "|", "bc", "|", "def" ]));
int[] a = [1, 0, 2, 3, 0, 4, 5, 6];
int[][] w = [ [1], [0], [2, 3], [0], [4, 5, 6] ];
assert(a .splitter!("a == b", Yes .keepSeparators)(0) .equal(w));
Example
Adjacent separators.
import std .algorithm .comparison : equal;
assert("|ab|" .splitter('|') .equal([ "", "ab", "" ]));
assert("ab" .splitter('|') .equal([ "ab" ]));
assert("a|b||c" .splitter('|') .equal([ "a", "b", "", "c" ]));
assert("hello world" .splitter(' ') .equal([ "hello", "", "world" ]));
auto a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
auto w = [ [1, 2], [], [3], [4, 5], [] ];
assert(a .splitter(0) .equal(w));
Example
Adjacent separators and keeping sentinels.
import std .algorithm .comparison : equal;
import std .typecons : Yes;
assert("|ab|" .splitter!("a == b", Yes .keepSeparators)('|')
.equal([ "", "|", "ab", "|", "" ]));
assert("ab" .splitter!("a == b", Yes .keepSeparators)('|')
.equal([ "ab" ]));
assert("a|b||c" .splitter!("a == b", Yes .keepSeparators)('|')
.equal([ "a", "|", "b", "|", "", "|", "c" ]));
assert("hello world" .splitter!("a == b", Yes .keepSeparators)(' ')
.equal([ "hello", " ", "", " ", "world" ]));
auto a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
auto w = [ [1, 2], [0], [], [0], [3], [0], [4, 5], [0], [] ];
assert(a .splitter!("a == b", Yes .keepSeparators)(0) .equal(w));
Example
Empty and separator-only ranges.
import std .algorithm .comparison : equal;
import std .range : empty;
assert("" .splitter('|') .empty);
assert("|" .splitter('|') .equal([ "", "" ]));
assert("||" .splitter('|') .equal([ "", "", "" ]));
Example
Empty and separator-only ranges and keeping sentinels.
import std .algorithm .comparison : equal;
import std .typecons : Yes;
import std .range : empty;
assert("" .splitter!("a == b", Yes .keepSeparators)('|') .empty);
assert("|" .splitter!("a == b", Yes .keepSeparators)('|')
.equal([ "", "|", "" ]));
assert("||" .splitter!("a == b", Yes .keepSeparators)('|')
.equal([ "", "|", "", "|", "" ]));
Example
Use a range for splitting
import std .algorithm .comparison : equal;
assert("a=>bc=>def" .splitter("=>") .equal([ "a", "bc", "def" ]));
assert("a|b||c" .splitter("||") .equal([ "a|b", "c" ]));
assert("hello world" .splitter(" ") .equal([ "hello", "world" ]));
int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [3, 0, 4, 5, 0] ];
assert(a .splitter([0, 0]) .equal(w));
a = [ 0, 0 ];
assert(a .splitter([0, 0]) .equal([ (int[]) .init, (int[]) .init ]));
a = [ 0, 0, 1 ];
assert(a .splitter([0, 0]) .equal([ [], [1] ]));
Example
Use a range for splitting
import std .algorithm .comparison : equal;
import std .typecons : Yes;
assert("a=>bc=>def" .splitter!("a == b", Yes .keepSeparators)("=>")
.equal([ "a", "=>", "bc", "=>", "def" ]));
assert("a|b||c" .splitter!("a == b", Yes .keepSeparators)("||")
.equal([ "a|b", "||", "c" ]));
assert("hello world" .splitter!("a == b", Yes .keepSeparators)(" ")
.equal([ "hello", " ", "world" ]));
int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [0, 0], [3, 0, 4, 5, 0] ];
assert(a .splitter!("a == b", Yes .keepSeparators)([0, 0]) .equal(w));
a = [ 0, 0 ];
assert(a .splitter!("a == b", Yes .keepSeparators)([0, 0])
.equal([ (int[]) .init, [0, 0], (int[]) .init ]));
a = [ 0, 0, 1 ];
assert(a .splitter!("a == b", Yes .keepSeparators)([0, 0])
.equal([ [], [0, 0], [1] ]));
Example
Custom predicate functions.
import std .algorithm .comparison : equal;
import std .ascii : toLower;
assert("abXcdxef" .splitter!"a.toLower == b"('x') .equal(
[ "ab", "cd", "ef" ]));
auto w = [ [0], [1], [2] ];
assert(w .splitter!"a.front == b"(1) .equal([ [[0]], [[2]] ]));
Example
Custom predicate functions.
import std .algorithm .comparison : equal;
import std .typecons : Yes;
import std .ascii : toLower;
assert("abXcdxef" .splitter!("a.toLower == b", Yes .keepSeparators)('x')
.equal([ "ab", "X", "cd", "x", "ef" ]));
auto w = [ [0], [1], [2] ];
assert(w .splitter!("a.front == b", Yes .keepSeparators)(1)
.equal([ [[0]], [[1]], [[2]] ]));
Example
Use splitter without a separator
import std .algorithm .comparison : equal;
import std .range .primitives : front;
assert(equal(splitter!(a => a == '|')("a|bc|def"), [ "a", "bc", "def" ]));
assert(equal(splitter!(a => a == ' ')("hello world"), [ "hello", "", "world" ]));
int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
int[][] w = [ [1, 2], [], [3], [4, 5], [] ];
assert(equal(splitter!(a => a == 0)(a), w));
a = [ 0 ];
assert(equal(splitter!(a => a == 0)(a), [ (int[]) .init, (int[]) .init ]));
a = [ 0, 1 ];
assert(equal(splitter!(a => a == 0)(a), [ [], [1] ]));
w = [ [0], [1], [2] ];
assert(equal(splitter!(a => a .front == 1)(w), [ [[0]], [[2]] ]));
Example
Leading separators, trailing separators, or no separators.
import std .algorithm .comparison : equal;
assert("|ab|" .splitter('|') .equal([ "", "ab", "" ]));
assert("ab" .splitter('|') .equal([ "ab" ]));
Example
Leading separators, trailing separators, or no separators.
import std .algorithm .comparison : equal;
import std .typecons : Yes;
assert("|ab|" .splitter!("a == b", Yes .keepSeparators)('|')
.equal([ "", "|", "ab", "|", "" ]));
assert("ab" .splitter!("a == b", Yes .keepSeparators)('|')
.equal([ "ab" ]));
Example
Splitter returns bidirectional ranges if the delimiter is a single element
import std .algorithm .comparison : equal;
import std .range : retro;
assert("a|bc|def" .splitter('|') .retro .equal([ "def", "bc", "a" ]));
Example
Splitter returns bidirectional ranges if the delimiter is a single element
import std .algorithm .comparison : equal;
import std .typecons : Yes;
import std .range : retro;
assert("a|bc|def" .splitter!("a == b", Yes .keepSeparators)('|')
.retro .equal([ "def", "|", "bc", "|", "a" ]));
Example
Splitting by word lazily
import std .ascii : isWhite;
import std .algorithm .comparison : equal;
import std .algorithm .iteration : splitter;
string str = "Hello World!";
assert(str .splitter!(isWhite) .equal(["Hello", "World!"]));
Function splitter
Lazily splits the character-based range s
into words, using whitespace as the
delimiter.
auto splitter(Range)
(
Range s
)
if (isSomeString!Range || isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && !isConvertibleToString!Range && isSomeChar!(ElementEncodingType!Range));
This function is character-range specific and, contrary to
splitter!(isWhite)
, runs of whitespace will be merged together
(no empty tokens will be produced).
Parameters
Name | Description |
---|---|
s | The character-based range to be split. Must be a string, or a random-access range of character types. |
Returns
An input range of slices of the original range split by whitespace.
Example
import std .algorithm .comparison : equal;
auto a = " a bcd ef gh ";
assert(equal(splitter(a), ["a", "bcd", "ef", "gh"][]));