Function std.algorithm.iteration.joiner
Lazily joins a range of ranges with a separator. The separator itself
is a range. If a separator is not provided, then the ranges are
joined directly without anything in between them (often called flatten
in other languages).
auto joiner(RoR, Separator)
(
RoR r,
Separator sep
);
auto joiner(RoR)
(
RoR r
)
if (isInputRange!RoR && isInputRange!(ElementType!RoR));
Parameters
Name | Description |
---|---|
r | An input range of input ranges to be joined. |
sep | A forward range of element(s) to serve as separators in the joined range. |
Returns
A range of elements in the joined range. This will be a bidirectional range if
both outer and inner ranges of RoR
are at least bidirectional ranges. Else if
both outer and inner ranges of RoR
are forward ranges, the returned range will
be likewise. Otherwise it will be only an input range. The
range bidirectionality
is propagated if no separator is specified.
See also
std
, which chains a sequence of ranges with compatible elements
into a single range.
Note
When both outer and inner ranges of RoR
are bidirectional and the joiner is
iterated from the back to the front, the separator will still be consumed from
front to back, even if it is a bidirectional range too.
Example
import std .algorithm .comparison : equal;
import std .conv : text;
assert(["abc", "def"] .joiner .equal("abcdef"));
assert(["Mary", "has", "a", "little", "lamb"]
.joiner("...")
.equal("Mary...has...a...little...lamb"));
assert(["", "abc"] .joiner("xyz") .equal("xyzabc"));
assert([""] .joiner("xyz") .equal(""));
assert(["", ""] .joiner("xyz") .equal("xyz"));
Example
import std .algorithm .comparison : equal;
import std .range : repeat;
assert([""] .joiner .equal(""));
assert(["", ""] .joiner .equal(""));
assert(["", "abc"] .joiner .equal("abc"));
assert(["abc", ""] .joiner .equal("abc"));
assert(["abc", "def"] .joiner .equal("abcdef"));
assert(["Mary", "has", "a", "little", "lamb"] .joiner .equal("Maryhasalittlelamb"));
assert("abc" .repeat(3) .joiner .equal("abcabcabc"));
Example
joiner allows in-place mutation!
import std .algorithm .comparison : equal;
auto a = [ [1, 2, 3], [42, 43] ];
auto j = joiner(a);
j .front = 44;
writeln(a); // [[44, 2, 3], [42, 43]]
assert(equal(j, [44, 2, 3, 42, 43]));
Example
insert characters fully lazily into a string
import std .algorithm .comparison : equal;
import std .range : chain, cycle, iota, only, retro, take, zip;
import std .format : format;
static immutable number = "12345678";
static immutable delimiter = ",";
auto formatted = number .retro
.zip(3 .iota .cycle .take(number .length))
.map!(z => chain(z[0] .only, z[1] == 2 ? delimiter : null))
.joiner
.retro;
static immutable expected = "12,345,678";
assert(formatted .equal(expected));
Example
joiner can be bidirectional
import std .algorithm .comparison : equal;
import std .range : retro;
auto a = [[1, 2, 3], [4, 5]];
auto j = a .joiner;
j .back = 44;
writeln(a); // [[1, 2, 3], [4, 44]]
assert(equal(j .retro, [44, 4, 3, 2, 1]));