Movatterモバイル変換


[0]ホーム

URL:


D Logo
Menu
Search

Library Reference

version 2.111.0

overview

Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page.Requires a signed-in GitHub account. This works well for small changes.If you'd like to make larger changes you may want to consider usinga local clone.

std.range

This module defines the notion of a range. Ranges generalize the concept ofarrays, lists, or anything that involves sequential access. This abstractionenables the same set of algorithms (seestd.algorithm) to be usedwith a vast variety of different concrete types. For example,a linear search algorithm such asstd.algorithm.searching.findworks not just for arrays, but for linked-lists, input files,incoming network data, etc.

GuidesThere are many articles available that can bolster understanding ranges:

SubmodulesThis module has two submodules:

Thestd.range.primitives submoduleprovides basic range functionality. It defines several templates for testingwhether a given object is a range, what kind of range it is, and providessome common range operations.
Thestd.range.interfaces submoduleprovides object-based interfaces for working with ranges via runtimepolymorphism.
The remainder of this module provides a rich set of range creation andcomposition templates that let you construct new ranges out of existing ranges:
chainConcatenates several ranges into a single range.
chooseChooses one of two ranges at runtime based on a boolean condition.
chooseAmongChooses one of several ranges at runtime based on an index.
chunksCreates a range that returns fixed-size chunks of the original range.
cycleCreates an infinite range that repeats the given forward range indefinitely. Good for implementing circular buffers.
dropCreates the range that results from discarding the firstn elements from the given range.
dropBackCreates the range that results from discarding the lastn elements from the given range.
dropExactlyCreates the range that results from discarding exactlyn of the first elements from the given range.
dropBackExactlyCreates the range that results from discarding exactlyn of the last elements from the given range.
dropOneCreates the range that results from discarding the first element from the given range.
dropBackOneCreates the range that results from discarding the last element from the given range.
enumerateIterates a range with an attached index variable.
evenChunksCreates a range that returns a number of chunks of approximately equal length from the original range.
frontTransversalCreates a range that iterates over the first elements of the given ranges.
generateCreates a range by successive calls to a given function. This allows to create ranges as a single delegate.
indexedCreates a range that offers a view of a given range as though its elements were reordered according to a given range of indices.
iotaCreates a range consisting of numbers between a starting point and ending point, spaced apart by a given interval.
lockstepIteratesn ranges in lockstep, for use in aforeach loop. Similar tozip, except thatlockstep is designed especially forforeach loops.
nullSinkAn output range that discards the data it receives.
onlyCreates a range that iterates over the given arguments.
padLeftPads a range to a specified length by adding a given element to the front of the range. Is lazy if the range has a known length.
padRightLazily pads a range to a specified length by adding a given element to the back of the range.
radialGiven a random-access range and a starting point, creates a range that alternately returns the next left and next right element to the starting point.
recurrenceCreates a forward range whose values are defined by a mathematical recurrence relation.
refRangePass a range by reference. Both the original range and the RefRange will always have the exact same elements. Any operation done on one will affect the other.
repeatCreates a range that consists of a single element repeatedn times, or an infinite range repeating that element indefinitely.
retroIterates a bidirectional range backwards.
roundRobinGivenn ranges, creates a new range that return then first elements of each range, in turn, then the second element of each range, and so on, in a round-robin fashion.
sequenceSimilar torecurrence, except that a random-access range is created.
slideCreates a range that returns a fixed-size sliding window over the original range. Unlike chunks, it advances a configurable number of items at a time, not one chunk at a time.
strideIterates a range with striden.
tailReturn a range advanced to withinn elements of the end of the given range.
takeCreates a sub-range consisting of only up to the firstn elements of the given range.
takeExactlyLiketake, but assumes the given range actually hasn elements, and therefore also defines thelength property.
takeNoneCreates a random-access range consisting of zero elements of the given range.
takeOneCreates a random-access range consisting of exactly the first element of the given range.
teeCreates a range that wraps a given range, forwarding along its elements while also calling a provided function with each element.
transposedTransposes a range of ranges.
transversalCreates a range that iterates over then'th elements of the given random-access ranges.
zipGivenn ranges, creates a range that successively returns a tuple of all the first elements, a tuple of all the second elements, etc.

SortednessRanges whose elements are sorted afford better efficiency with certainoperations. For this, theassumeSorted function can be used toconstruct aSortedRange from a pre-sorted range. Thestd.algorithm.sorting.sort function also convenientlyreturns aSortedRange.SortedRange objects provide some additionalrange operations that take advantage of the fact that the range is sorted.

Sourcestd/range/package.d

License:
Boost License 1.0.
Authors:
Andrei Alexandrescu, David Simcha,Jonathan M Davis, and Jack Stouffer. Credit for some of the ideas in building this module goes toLeonardo Maffi.
autoretro(Range)(Ranger)
if (isBidirectionalRange!(Unqual!Range));
Iterates a bidirectional range backwards. The original range can beaccessed by using thesource property. Applying retro twice tothe same range yields the original range.
Parameters:
Rangerthe bidirectional range to iterate backwards
Returns:
A bidirectional range with length ifr also provides a length. Or, ifr is a random access range, then the return value will be random access as well.
See Also:
std.algorithm.mutation.reverse for mutating the source range directly.
Examples:
import std.algorithm.comparison : equal;int[5] a = [ 1, 2, 3, 4, 5 ];int[5] b = [ 5, 4, 3, 2, 1 ];assert(equal(retro(a[]), b[]));assert(retro(a[]).sourceis a[]);assert(retro(retro(a[]))is a[]);
autostride(Range)(Ranger, size_tn)
if (isInputRange!(Unqual!Range));
Iterates ranger with striden. If the range is arandom-access range, moves by indexing into the range; otherwise,moves by successive calls topopFront. Applying stride twice tothe same range results in a stride with a step that is theproduct of the two applications. It is an error forn to be 0.
Parameters:
Rangertheinput range to stride over
size_tnthe number of elements to skip over
Returns:
At minimum, an input range. The resulting range will adopt the range primitives of the underlying range as long asstd.range.primitives.hasLength istrue.
Examples:
import std.algorithm.comparison : equal;int[] a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];assert(equal(stride(a, 3), [ 1, 4, 7, 10 ][]));writeln(stride(stride(a, 2), 3));// stride(a, 6)
autochain(Ranges...)(Rangesrs)
if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void));
Spans multiple ranges in sequence. The functionchain takes anynumber of ranges and returns aChain!(R1, R2,...) object. Theranges may be different, but they must have the same element type. Theresult is a range that offers thefront,popFront, andempty primitives. If all input ranges offer random access andlength,Chain offers them as well.
Note that repeated random access of the resulting range is likelyto perform somewhat badly since lengths of the ranges in the chain have to beadded up for each random access operation. Random access to elements ofthe first remaining range is still efficient.
If only one range is offered toChain orchain, theChain type exits the picture by aliasing itself directly to thatrange's type.
Parameters:
Rangesrstheinput ranges to chain together
Returns:
An input range at minimum. If all of the ranges inrs provide a range primitive, the returned range will also provide that range primitive.
See Also:
only to chain values to a range
Examples:
import std.algorithm.comparison : equal;int[] arr1 = [ 1, 2, 3, 4 ];int[] arr2 = [ 5, 6 ];int[] arr3 = [ 7 ];auto s =chain(arr1, arr2, arr3);writeln(s.length);// 7writeln(s[5]);// 6assert(equal(s, [1, 2, 3, 4, 5, 6, 7][]));
Examples:
Range primitives are carried over to the returned range if all of the ranges provide them
import std.algorithm.comparison : equal;import std.algorithm.sorting : sort;int[] arr1 = [5, 2, 8];int[] arr2 = [3, 7, 9];int[] arr3 = [1, 4, 6];// in-place sorting across all of the arraysauto s = arr1.chain(arr2, arr3).sort;assert(s.equal([1, 2, 3, 4, 5, 6, 7, 8, 9]));assert(arr1.equal([1, 2, 3]));assert(arr2.equal([4, 5, 6]));assert(arr3.equal([7, 8, 9]));
Examples:
Due to safe type promotion in D, chaining together differentcharacter ranges results in auint range.
UsebyChar,byWchar,andbyDchar on the rangesto get the type you need.
import std.utf : byChar, byCodeUnit;auto s1 ="string one";auto s2 ="string two";// s1 and s2 front is dchar because of auto-decodingstaticassert(is(typeof(s1.front) ==dchar) &&is(typeof(s2.front) ==dchar));auto r1 = s1.chain(s2);// chains of ranges of the same character type give that same typestaticassert(is(typeof(r1.front) ==dchar));auto s3 ="string three".byCodeUnit;staticassert(is(typeof(s3.front) ==immutablechar));auto r2 = s1.chain(s3);// chaining ranges of mixed character types gives `dchar`staticassert(is(typeof(r2.front) ==dchar));// use byChar on character ranges to correctly convert them to UTF-8auto r3 = s1.byChar.chain(s3);staticassert(is(typeof(r3.front) ==immutablechar));
autochoose(R1, R2)(boolcondition, return scope R1r1, return scope R2r2)
if (isInputRange!(Unqual!R1) && isInputRange!(Unqual!R2) && !is(CommonType!(ElementType!(Unqual!R1), ElementType!(Unqual!R2)) == void));
Choose one of two ranges at runtime depending on a Boolean condition.
The ranges may be different, but they must have compatible element types (i.e.CommonType must exist for the two element types). The result is a rangethat offers the weakest capabilities of the two (e.g.ForwardRange ifR1 is a random-access range andR2 is a forward range).
Parameters:
boolconditionwhich range to choose:r1 iftrue,r2 otherwise
R1r1the "true" range
R2r2the "false" range
Returns:
A range type dependent onR1 andR2.
Examples:
import std.algorithm.comparison : equal;import std.algorithm.iteration : filter, map;auto data1 = only(1, 2, 3, 4).filter!(a => a != 3);auto data2 = only(5, 6, 7, 8).map!(a => a + 1);// choose() is primarily useful when you need to select one of two ranges// with different types at runtime.staticassert(!is(typeof(data1) ==typeof(data2)));auto chooseRange(bool pickFirst){// The returned range is a common wrapper type that can be used for// returning or storing either range without running into a type error.returnchoose(pickFirst, data1, data2);// Simply returning the chosen range without using choose() does not// work, because map() and filter() return different types.//return pickFirst ? data1 : data2; // does not compile}auto result = chooseRange(true);assert(result.equal(only(1, 2, 4)));result = chooseRange(false);assert(result.equal(only(6, 7, 8, 9)));
autochooseAmong(Ranges...)(size_tindex, return scope Rangesrs)
if (Ranges.length >= 2 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, Ranges)) == void));
Choose one of multiple ranges at runtime.
The ranges may be different, but they must have compatible element types. Theresult is a range that offers the weakest capabilities of allRanges.
Parameters:
size_tindexwhich range to choose, must be less than the number of ranges
Rangesrstwo or more ranges
Returns:
The indexed range. If rs consists of only one range, the return type is an alias of that range's type.
Examples:
auto test(){import std.algorithm.comparison : equal;int[4] sarr1 = [1, 2, 3, 4];int[2] sarr2 = [5, 6];int[1] sarr3 = [7];auto arr1 = sarr1[];auto arr2 = sarr2[];auto arr3 = sarr3[];    {auto s =chooseAmong(0, arr1, arr2, arr3);auto t = s.save;        writeln(s.length);// 4        writeln(s[2]);// 3        s.popFront();assert(equal(t, only(1, 2, 3, 4)));    }    {auto s =chooseAmong(1, arr1, arr2, arr3);        writeln(s.length);// 2        s.front = 8;assert(equal(s, only(8, 6)));    }    {auto s =chooseAmong(1, arr1, arr2, arr3);        writeln(s.length);// 2        s[1] = 9;assert(equal(s, only(8, 9)));    }    {auto s =chooseAmong(1, arr2, arr1, arr3)[1 .. 3];        writeln(s.length);// 2assert(equal(s, only(2, 3)));    }    {auto s =chooseAmong(0, arr1, arr2, arr3);        writeln(s.length);// 4        writeln(s.back);// 4        s.popBack();        s.back = 5;assert(equal(s, only(1, 2, 5)));        s.back = 3;assert(equal(s, only(1, 2, 3)));    }    {uint[5] foo = [1, 2, 3, 4, 5];uint[5] bar = [6, 7, 8, 9, 10];auto c =chooseAmong(1, foo[], bar[]);        writeln(c[3]);// 9        c[3] = 42;        writeln(c[3]);// 42        writeln(c.moveFront());// 6        writeln(c.moveBack());// 10        writeln(c.moveAt(4));// 10    }    {import std.range : cycle;auto s =chooseAmong(0, cycle(arr2), cycle(arr3));assert(isInfinite!(typeof(s)));assert(!s.empty);        writeln(s[100]);// 8        writeln(s[101]);// 9assert(s[0 .. 3].equal(only(8, 9, 8)));    }return 0;}// works at runtimeauto a = test();// and at compile timestatic b = test();
autoroundRobin(Rs...)(Rsrs)
if (Rs.length > 1 && allSatisfy!(isInputRange, staticMap!(Unqual, Rs)));
roundRobin(r1, r2, r3) yieldsr1.front, thenr2.front,thenr3.front, after which it pops off one element from each andcontinues again fromr1. For example, if two ranges are involved,it alternately yields elements off the two ranges.roundRobinstops after it has consumed all ranges (skipping over the ones thatfinish early).
Examples:
import std.algorithm.comparison : equal;int[] a = [ 1, 2, 3 ];int[] b = [ 10, 20, 30, 40 ];auto r =roundRobin(a, b);assert(equal(r, [ 1, 10, 2, 20, 3, 30, 40 ]));
Examples:
roundRobin can be used to create "interleave" functionality which inserts an element between each element in a range.
import std.algorithm.comparison : equal;auto interleave(R, E)(R range, E element)if ((isInputRange!R && hasLength!R) || isForwardRange!R){staticif (hasLength!R)immutable len = range.length;elseimmutable len = range.save.walkLength;returnroundRobin(        range,        element.repeat(len - 1)    );}assert(interleave([1, 2, 3], 0).equal([1, 0, 2, 0, 3]));
autoradial(Range, I)(Ranger, IstartingIndex)
if (isRandomAccessRange!(Unqual!Range) && hasLength!(Unqual!Range) && hasSlicing!(Unqual!Range) && isIntegral!I);

autoradial(R)(Rr)
if (isRandomAccessRange!(Unqual!R) && hasLength!(Unqual!R) && hasSlicing!(Unqual!R));
Iterates a random-access range starting from a given point andprogressively extending left and right from that point. If no initialpoint is given, iteration starts from the middle of therange. Iteration spans the entire range.
WhenstartingIndex is 0 the range will be fully iterated in orderand in reverse order whenr.length is given.
Parameters:
Rangera random access range with length and slicing
IstartingIndexthe index to begin iteration from
Returns:
A forward range with length
Examples:
import std.algorithm.comparison : equal;int[] a = [ 1, 2, 3, 4, 5 ];assert(equal(radial(a), [ 3, 4, 2, 5, 1 ]));a = [ 1, 2, 3, 4 ];assert(equal(radial(a), [ 2, 3, 1, 4 ]));// If the left end is reached first, the remaining elements on the right// are concatenated in order:a = [ 0, 1, 2, 3, 4, 5 ];assert(equal(radial(a, 1), [ 1, 2, 0, 3, 4, 5 ]));// If the right end is reached first, the remaining elements on the left// are concatenated in reverse order:assert(equal(radial(a, 4), [ 4, 5, 3, 2, 1, 0 ]));
Take!Rtake(R)(Rinput, size_tn)
if (isInputRange!(Unqual!R));

structTake(Range) if (isInputRange!(Unqual!Range) && !(!isInfinite!(Unqual!Range) && hasSlicing!(Unqual!Range) || is(Range T ==Take!T)));

templateTake(R) if (isInputRange!(Unqual!R) && (!isInfinite!(Unqual!R) && hasSlicing!(Unqual!R) || is(R T ==Take!T)))
Lazily takes only up ton elements of a range. This isparticularly useful when using with infinite ranges.
UnliketakeExactly,take does not require that therearen or more elements ininput. As a consequence, lengthinformation is not applied to the result unlessinput also haslength information.
Parameters:
Rinputaninput range to iterate over up ton times
size_tnthe number of elements to take
Returns:
At minimum, an input range. If the range offers random access andlength,take offers them as well.
Examples:
import std.algorithm.comparison : equal;int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];auto s =take(arr1, 5);writeln(s.length);// 5writeln(s[4]);// 5assert(equal(s, [ 1, 2, 3, 4, 5 ][]));
Examples:
If the range runs out beforen elements,take simply returns the entire range (unliketakeExactly, which will cause an assertion failure if the range ends prematurely):
import std.algorithm.comparison : equal;int[] arr2 = [ 1, 2, 3 ];auto t =take(arr2, 5);writeln(t.length);// 3assert(equal(t, [ 1, 2, 3 ]));
autotakeExactly(R)(Rrange, size_tn)
if (isInputRange!R);
Similar totake, but assumes thatrange has at leastn elements. Consequently, the result oftakeExactly(range, n)always defines thelength property (and initializes it ton)even whenrange itself does not definelength.
The result oftakeExactly is identical to that oftake incases where the original range defineslength or is infinite.
Unliketake, however, it is illegal to pass a range with less thann elements totakeExactly; this will cause an assertion failure.
Examples:
import std.algorithm.comparison : equal;auto a = [ 1, 2, 3, 4, 5 ];auto b =takeExactly(a, 3);assert(equal(b, [1, 2, 3]));staticassert(is(typeof(b.length) == size_t));writeln(b.length);// 3writeln(b.front);// 1writeln(b.back);// 3
autotakeOne(R)(Rsource)
if (isInputRange!R);
Returns a range with at most one element; for example,takeOne([42, 43, 44]) returns a range consisting of the integer42. CallingpopFront() off that range renders it empty.
In effecttakeOne(r) is somewhat equivalent totake(r, 1) but incertain interfaces it is important to know statically that the range may onlyhave at most one element.
The type returned bytakeOne is a random-access range with lengthregardless ofR's capabilities, as long as it is a forward range.(another feature that distinguishestakeOne fromtake). If(D R) is an input range but not a forward range, return type is an inputrange with all random-access capabilities except save.
Examples:
auto s =takeOne([42, 43, 44]);staticassert(isRandomAccessRange!(typeof(s)));writeln(s.length);// 1assert(!s.empty);writeln(s.front);// 42s.front = 43;writeln(s.front);// 43writeln(s.back);// 43writeln(s[0]);// 43s.popFront();writeln(s.length);// 0assert(s.empty);
autotakeNone(R)()
if (isInputRange!R);
Returns an empty range which is statically known to be empty and is guaranteed to havelength and be random access regardless ofR's capabilities.
Examples:
auto range =takeNone!(int[])();writeln(range.length);// 0assert(range.empty);
autotakeNone(R)(Rrange)
if (isInputRange!R);
Creates an empty range from the given range inΟ(1). If it can, it will return the same range type. If not, it will returntakeExactly(range, 0).
Examples:
import std.algorithm.iteration : filter;assert(takeNone([42, 27, 19]).empty);assert(takeNone("dlang.org").empty);assert(takeNone(filter!"true"([42, 27, 19])).empty);
autotail(Range)(Rangerange, size_tn)
if (isInputRange!Range && !isInfinite!Range && (hasLength!Range || isForwardRange!Range));
Return a range advanced to within_n elements of the end ofrange.
Intended as the range equivalent of the Unixtail utility. When the length ofrange is less than or equal to_n,range is returned as-is.
Completes inΟ(1) steps for ranges that support slicing and have length. Completes inΟ(range.length) time for all other ranges.
Parameters:
Rangerangerange to get tail of
size_tnmaximum number of elements to include in tail
Returns:
Returns the tail ofrange augmented with length information
Examples:
// tail -c nwriteln([1, 2, 3].tail(1));// [3]writeln([1, 2, 3].tail(2));// [2, 3]writeln([1, 2, 3].tail(3));// [1, 2, 3]writeln([1, 2, 3].tail(4));// [1, 2, 3]writeln([1, 2, 3].tail(0).length);// 0// tail --lines=nimport std.algorithm.comparison : equal;import std.algorithm.iteration : joiner;import std.exception : assumeWontThrow;import std.string : lineSplitter;assert("one\ntwo\nthree"    .lineSplitter    .tail(2)    .joiner("\n")    .equal("two\nthree")    .assumeWontThrow);
Rdrop(R)(Rrange, size_tn)
if (isInputRange!R);

RdropBack(R)(Rrange, size_tn)
if (isBidirectionalRange!R);
Convenience function which callsstd.range.primitives.popFrontN(range,n) and returnsrange.drop makes it easier to pop elements from a range and then pass it to another function within a single expression, whereaspopFrontN would require multiple statements.
dropBack provides the same functionality but instead callsstd.range.primitives.popBackN(range,n)

Notedrop anddropBack will only popup ton elements but will stop if the range is empty first. In other languages this is sometimes calledskip.

Parameters:
Rrangetheinput range to drop from
size_tnthe number of elements to drop
Returns:
range with up ton elements dropped
See Also:
Examples:
import std.algorithm.comparison : equal;writeln([0, 2, 1, 5, 0, 3].drop(3));// [5, 0, 3]writeln("hello world".drop(6));// "world"assert("hello world".drop(50).empty);assert("hello world".take(6).drop(3).equal("lo "));
Examples:
import std.algorithm.comparison : equal;writeln([0, 2, 1, 5, 0, 3].dropBack(3));// [0, 2, 1]writeln("hello world".dropBack(6));// "hello"assert("hello world".dropBack(50).empty);assert("hello world".drop(4).dropBack(4).equal("o w"));
RdropExactly(R)(Rrange, size_tn)
if (isInputRange!R);

RdropBackExactly(R)(Rrange, size_tn)
if (isBidirectionalRange!R);
Similar todrop anddropBack but they callrange.popFrontExactly(n) andrange.popBackExactly(n) instead.

NoteUnlikedrop,dropExactly will assume that the range holds at leastn elements. This makesdropExactly faster thandrop, but it also means that ifrange does not contain at leastn elements, it will attempt to callpopFront on an empty range, which is undefined behavior. So, only usepopFrontExactly when it is guaranteed thatrange holds at leastn elements.

Parameters:
Rrangetheinput range to drop from
size_tnthe number of elements to drop
Returns:
range withn elements dropped
See Also:
Examples:
import std.algorithm.comparison : equal;import std.algorithm.iteration : filterBidirectional;auto a = [1, 2, 3];writeln(a.dropExactly(2));// [3]writeln(a.dropBackExactly(2));// [1]string s ="日本語";writeln(s.dropExactly(2));// "語"writeln(s.dropBackExactly(2));// "日"auto bd = filterBidirectional!"true"([1, 2, 3]);assert(bd.dropExactly(2).equal([3]));assert(bd.dropBackExactly(2).equal([1]));
RdropOne(R)(Rrange)
if (isInputRange!R);

RdropBackOne(R)(Rrange)
if (isBidirectionalRange!R);
Convenience function which callsrange.popFront() and returnsrange.dropOne makes it easier to pop an element from a range and then pass it to another function within a single expression, whereaspopFront would require multiple statements.
dropBackOne provides the same functionality but instead callsrange.popBack().
Examples:
import std.algorithm.comparison : equal;import std.algorithm.iteration : filterBidirectional;import std.container.dlist : DList;auto dl = DList!int(9, 1, 2, 3, 9);assert(dl[].dropOne().dropBackOne().equal([1, 2, 3]));auto a = [1, 2, 3];writeln(a.dropOne());// [2, 3]writeln(a.dropBackOne());// [1, 2]string s ="日本語";import std.exception : assumeWontThrow;assert(assumeWontThrow(s.dropOne() =="本語"));assert(assumeWontThrow(s.dropBackOne() =="日本"));auto bd = filterBidirectional!"true"([1, 2, 3]);assert(bd.dropOne().equal([2, 3]));assert(bd.dropBackOne().equal([1, 2]));
structRepeat(T);

Repeat!Trepeat(T)(Tvalue);

Take!(Repeat!T)repeat(T)(Tvalue, size_tn);
Create a range which repeats one value.
Parameters:
Tvaluethe value to repeat
size_tnthe number of times to repeatvalue
Returns:
Ifn is not defined, an infinite random access range with slicing.
Ifn is defined, a random access range with slicing.
Examples:
import std.algorithm.comparison : equal;assert(5.repeat().take(4).equal([5, 5, 5, 5]));
Examples:
import std.algorithm.comparison : equal;assert(5.repeat(4).equal([5, 5, 5, 5]));
@property inout(T)front() inout;

@property inout(T)back() inout;

enum boolempty;

voidpopFront();

voidpopBack();

@property autosave() inout;

inout(T)opIndex(size_t) inout;

autoopSlice(size_ti, size_tj);

enum autoopDollar;

autoopSlice(size_t, DollarToken) inout;
Range primitives
autogenerate(Fun)(Funfun)
if (isCallable!fun);

autogenerate(alias fun)()
if (isCallable!fun);
Given callable (std.traits.isCallable)fun, create as a rangewhose front is defined by successive calls tofun().This is especially useful to call function with global side effects (randomfunctions), or to create ranges expressed as a single delegate, rather thanan entirefront/popFront/empty structure.fun maybe be passed either a template alias parameter (existingfunction, delegate, struct type definingstatic opCall) ora run-time value argument (delegate, function object).The result range models an InputRange(std.range.primitives.isInputRange).The resulting range will callfun() on construction, and every call topopFront, and the cached value will be returned whenfront is called.
Returns:
aninputRange where each element represents another call to fun.
Examples:
import std.algorithm.comparison : equal;import std.algorithm.iteration : map;int i = 1;auto powersOfTwo =generate!(() => i *= 2)().take(10);assert(equal(powersOfTwo, iota(1, 11).map!"2^^a"()));
Examples:
import std.algorithm.comparison : equal;//Returns a run-time delegateauto infiniteIota(T)(T low, T high){    T i = high;return (){if (i == high) i = low;return i++;};}//adapted as a range.assert(equal(generate(infiniteIota(1, 4)).take(10), [1, 2, 3, 1, 2, 3, 1, 2, 3, 1]));
Examples:
import std.format : format;import std.random : uniform;auto r =generate!(() => uniform(0, 6)).take(10);format("%(%s %)", r);
structCycle(R) if (isForwardRange!R && !isInfinite!R);

templateCycle(R) if (isInfinite!R)

structCycle(R) if (isStaticArray!R);

autocycle(R)(Rinput)
if (isInputRange!R);

Cycle!Rcycle(R)(Rinput, size_tindex = 0)
if (isRandomAccessRange!R && !isInfinite!R);

@system Cycle!Rcycle(R)(ref Rinput, size_tindex = 0)
if (isStaticArray!R);
Repeats the given forward range ad infinitum. If the original range isinfinite (fact that would makeCycle the identity application),Cycle detects that and aliases itself to the range typeitself. That works for non-forward ranges too.If the original range has random access,Cycle offersrandom access and also offers a constructor taking an initial positionindex.Cycle works with static arrays in addition to ranges,mostly for performance reasons.

NoteThe input range must not be empty.

TipThis is a great way to implement simple circular buffers.

Examples:
import std.algorithm.comparison : equal;import std.range :cycle, take;// Here we create an infinitive cyclic sequence from [1, 2]// (i.e. get here [1, 2, 1, 2, 1, 2 and so on]) then// take 5 elements of this sequence (so we have [1, 2, 1, 2, 1])// and compare them with the expected values for equality.assert(cycle([1, 2]).take(5).equal([ 1, 2, 1, 2, 1 ]));
this(Rinput, size_tindex = 0);

@property ref autofront();

@property ref autofront() const;

@property voidfront(ElementType!Rval);

enum boolempty;

voidpopFront();

ref autoopIndex(size_tn);

ref autoopIndex(size_tn) const;

voidopIndexAssign(ElementType!Rval, size_tn);

@property Cyclesave();

enum autoopDollar;

autoopSlice(size_ti, size_tj);

autoopSlice(size_ti, DollarToken);
Range primitives
structZip(Ranges...) if (Ranges.length && allSatisfy!(isInputRange, Ranges));

autozip(Ranges...)(Rangesranges)
if (Ranges.length && allSatisfy!(isInputRange, Ranges));

autozip(Ranges...)(StoppingPolicysp, Rangesranges)
if (Ranges.length && allSatisfy!(isInputRange, Ranges));
Iterate several ranges in lockstep. The element type is a proxy tuple that allows accessing the current element in thenth range by usinge[n].
zip is similar tolockstep, butlockstep doesn't bundle its elements and uses theopApply protocol.lockstep allows reference access to the elements inforeach iterations.
Parameters:
StoppingPolicyspcontrols whatzip will do if the ranges are different lengths
Rangesrangesthe ranges to zip together
Returns:
At minimum, an input range.Zip offers the lowest range facilities of all components, e.g. it offers random access iff all ranges offer random access, and also offers mutation and swapping if all ranges offer it. Due to this,Zip is extremely powerful because it allows manipulating several ranges in lockstep.
Throws:
AnException if all of the ranges are not the same length andsp is set toStoppingPolicy.requireSameLength.

LimitationsThe@nogc andnothrow attributes cannot be inferred for theZip struct becauseStoppingPolicy can vary at runtime. This limitation is not shared by the anonymous range returned by thezip function when not given an explicitStoppingPolicy as an argument.

Examples:
import std.algorithm.comparison : equal;import std.algorithm.iteration : map;// pairwise sumauto arr = only(0, 1, 2);auto part1 =zip(arr, arr.dropOne).map!"a[0] + a[1]";assert(part1.equal(only(1, 3)));
Examples:
import std.conv : to;int[] a = [ 1, 2, 3 ];string[] b = ["a","b","c" ];string[] result;foreach (tup;zip(a, b)){    result ~= tup[0].to!string ~ tup[1];}writeln(result);// ["1a", "2b", "3c"]size_t idx = 0;// unpacking tuple elements with foreachforeach (e1, e2;zip(a, b)){    writeln(e1);// a[idx]    writeln(e2);// b[idx]    ++idx;}
Examples:
zip is powerful - the following code sorts two arrays in parallel:
import std.algorithm.sorting : sort;int[] a = [ 1, 2, 3 ];string[] b = ["a","c","b" ];zip(a, b).sort!((t1, t2) => t1[0] > t2[0]);writeln(a);// [3, 2, 1]// b is sorted according to a's sortingwriteln(b);// ["b", "c", "a"]
this(Rrs, StoppingPolicys = StoppingPolicy.shortest);
Builds an object. Usually this is invoked indirectly by using thezip function.
enum boolempty;
Returnstrue if the range is at end. The test depends on the stopping policy.
@property Zipsave();
@property ElementTypefront();
Returns the current iterated element.
@property voidfront(ElementTypev);
Sets the front of all iterated ranges.
ElementTypemoveFront();
Moves out the front.
@property ElementTypeback();
Returns the rightmost element.
ElementTypemoveBack();
Moves out the back.
Returns the rightmost element.
@property voidback(ElementTypev);
Returns the current iterated element.
Returns the rightmost element.
voidpopFront();
Advances to the next element in all controlled ranges.
voidpopBack();
CallspopBack for all controlled ranges.
@property autolength();
Returns the length of this range. Defined only if all ranges definelength.
aliasopDollar = length;
Returns the length of this range. Defined only if all ranges definelength.
autoopSlice(size_tfrom, size_tto);
Returns a slice of the range. Defined only if all range define slicing.
ElementTypeopIndex(size_tn);
Returns thenth element in the composite range. Defined if all ranges offer random access.
voidopIndexAssign(ElementTypev, size_tn);
Assigns to thenth element in the composite range. Defined if all ranges offer random access.
Returns thenth element in the composite range. Defined if all ranges offer random access.
ElementTypemoveAt(size_tn);
Destructively reads thenth element in the composite range. Defined if all ranges offer random access.
Returns thenth element in the composite range. Defined if all ranges offer random access.
enumStoppingPolicy: int;
Dictates how iteration in azip andlockstep should stop. By default stop at the end of the shortest of all ranges.
Examples:
import std.algorithm.comparison : equal;import std.exception : assertThrown;import std.range.primitives;import std.typecons : tuple;auto a = [1, 2, 3];auto b = [4, 5, 6, 7];auto shortest = zip(StoppingPolicy.shortest, a, b);assert(shortest.equal([    tuple(1, 4),    tuple(2, 5),    tuple(3, 6)]));auto longest = zip(StoppingPolicy.longest, a, b);assert(longest.equal([    tuple(1, 4),    tuple(2, 5),    tuple(3, 6),    tuple(0, 7)]));auto same = zip(StoppingPolicy.requireSameLength, a, b);same.popFrontN(3);assertThrown!Exception(same.popFront);
shortest
Stop when the shortest range is exhausted
longest
Stop when the longest range is exhausted
requireSameLength
Require that all ranges are equal
structLockstep(Ranges...) if (Ranges.length > 1 && allSatisfy!(isInputRange, Ranges));

Lockstep!Rangeslockstep(Ranges...)(Rangesranges)
if (allSatisfy!(isInputRange, Ranges));

Lockstep!Rangeslockstep(Ranges...)(Rangesranges, StoppingPolicys)
if (allSatisfy!(isInputRange, Ranges));
Iterate multiple ranges in lockstep using aforeach loop. In contrast tozip it allows reference access to its elements. If only a single range is passed in, theLockstep aliases itself away. If the ranges are of different lengths ands ==StoppingPolicy.shortest stop after the shortest range is empty. If the ranges are of different lengths ands ==StoppingPolicy.requireSameLength, throw an exception.s may not beStoppingPolicy.longest, and passing this will throw an exception.
Iterating overLockstep in reverse and with an index is only possible whens ==StoppingPolicy.requireSameLength, in order to preserve indexes. If an attempt is made at iterating in reverse whens ==StoppingPolicy.shortest, an exception will be thrown.
By defaultStoppingPolicy is set toStoppingPolicy.shortest.
See Also:
zip
lockstep is similar tozip, butzip bundles its elements and returns a range.lockstep also supports reference access. Usezip if you want to pass the result to a range function.
Examples:
int[6] arr1 = [1,2,3,4,5,100];int[5] arr2 = [6,7,8,9,10];foreach (ref a, b;lockstep(arr1[], arr2[])){    a += b;}writeln(arr1);// [7, 9, 11, 13, 15, 100]
Examples:
Lockstep also supports iterating with an index variable:
int[3] arr1 = [1,2,3];int[3] arr2 = [4,5,6];foreach (index, a, b;lockstep(arr1[], arr2[])){    writeln(arr1[index]);// a    writeln(arr2[index]);// b}
this(Rangesranges, StoppingPolicysp = StoppingPolicy.shortest);
structRecurrence(alias fun, StateType, size_t stateSize);

Recurrence!(fun, CommonType!State, State.length)recurrence(alias fun, State...)(Stateinitial);
Creates a mathematical sequence given the initial values and arecurrence function that computes the next value from the existingvalues. The sequence comes in the form of an infinite forwardrange. The typeRecurrence itself is seldom used directly; mostoften, recurrences are obtained by calling the functionrecurrence.
When callingrecurrence, the function that computes the nextvalue is specified as a template argument, and the initial values inthe recurrence are passed as regular arguments. For example, in aFibonacci sequence, there are two initial values (and therefore astate size of 2) because computing the next Fibonacci value needs thepast two values.
The signature of this function should be:
auto fun(R)(R state, size_t n)
wheren will be the index of the current value, andstate will be anopaque state vector that can be indexed with array-indexing notationstate[i], where valid values ofi range from(n - 1) to(n - State.length).
If the function is passed in string form, the state has name"a"and the zero-based index in the recurrence has name"n". Thegiven string must return the desired value fora[n] givena[n - 1],a[n - 2],a[n - 3],...,a[n - stateSize]. Thestate size is dictated by the number of arguments passed to the calltorecurrence. TheRecurrence struct itself takes care ofmanaging the recurrence's state and shifting it appropriately.
Examples:
import std.algorithm.comparison : equal;// The Fibonacci numbers, using function in string form:// a[0] = 1, a[1] = 1, and compute a[n+1] = a[n-1] + a[n]auto fib =recurrence!("a[n-1] + a[n-2]")(1, 1);assert(fib.take(10).equal([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]));// The factorials, using function in lambda form:auto fac =recurrence!((a,n) => a[n-1] * n)(1);assert(take(fac, 10).equal([    1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]));// The triangular numbers, using function in explicit form:static size_t genTriangular(R)(R state, size_t n){return state[n-1] + n;}auto tri =recurrence!genTriangular(0);assert(take(tri, 10).equal([0, 1, 3, 6, 10, 15, 21, 28, 36, 45]));
structSequence(alias fun, State);

autosequence(alias fun, State...)(Stateargs);
Sequence is similar toRecurrence except that iteration is presented in the so-called closed form. This means that thenth element in the series is computable directly from the initial values andn itself. This implies that the interface offered bySequence is a random-access range, as opposed to the regularRecurrence, which only offers forward iteration.
The state of the sequence is stored as aTuple so it can be heterogeneous.
Examples:
Odd numbers, using function in string form:
auto odds =sequence!("a[0] + n * a[1]")(1, 2);writeln(odds.front);// 1odds.popFront();writeln(odds.front);// 3odds.popFront();writeln(odds.front);// 5
Examples:
Triangular numbers, using function in lambda form:
auto tri =sequence!((a,n) => n*(n+1)/2)();// Note random accesswriteln(tri[0]);// 0writeln(tri[3]);// 6writeln(tri[1]);// 1writeln(tri[4]);// 10writeln(tri[2]);// 3
Examples:
Fibonacci numbers, using function in explicit form:
import std.math.exponential : pow;import std.math.rounding : round;import std.math.algebraic : sqrt;staticulong computeFib(S)(S state, size_t n){// Binet's formulareturncast(ulong)(round((pow(state[0], n+1) - pow(state[1], n+1)) /                             state[2]));}auto fib =sequence!computeFib(    (1.0 + sqrt(5.0)) / 2.0,// Golden Ratio    (1.0 - sqrt(5.0)) / 2.0,// Conjugate of Golden Ratio    sqrt(5.0));// Note random access with [] operatorwriteln(fib[1]);// 1writeln(fib[4]);// 5writeln(fib[3]);// 3writeln(fib[2]);// 2writeln(fib[9]);// 55
autoiota(B, E, S)(Bbegin, Eend, Sstep)
if ((isIntegral!(CommonType!(B, E)) || isPointer!(CommonType!(B, E))) && isIntegral!S);

autoiota(B, E)(Bbegin, Eend)
if (isFloatingPoint!(CommonType!(B, E)));

autoiota(B, E)(Bbegin, Eend)
if (isIntegral!(CommonType!(B, E)) || isPointer!(CommonType!(B, E)));

autoiota(E)(Eend)
if (is(typeof(iota(E(0),end))));

autoiota(B, E, S)(Bbegin, Eend, Sstep)
if (isFloatingPoint!(CommonType!(B, E, S)));

autoiota(B, E)(Bbegin, Eend)
if (!isIntegral!(CommonType!(B, E)) && !isFloatingPoint!(CommonType!(B, E)) && !isPointer!(CommonType!(B, E)) && is(typeof((ref B b){++b;})) && (is(typeof(B.init < E.init)) || is(typeof(B.init == E.init))));
Creates a range of values that span the given starting and stopping values.
Parameters:
BbeginThe starting value.
EendThe value that serves as the stopping criterion. This value is not included in the range.
SstepThe value to add to the current value at each iteration.
Returns:
A range that goes through the numbersbegin,begin + step,begin + 2 * step,..., up to and excludingend.
The two-argument overloads havestep = 1. Ifbegin < end && step < 0 orbegin > end && step > 0 orbegin == end, then an empty range is returned. Ifstep == 0 thenbegin == end is an error.
For built-in types, the range returned is a random access range. For user-defined types that support++, the range is an input range.
An integral iota also supportsin operator from the right. It takes the stepping into account, the integral won't be considered contained if it falls between two consecutive values of the range.contains does the same as in, but from lefthand side.

Example

void main(){import std.stdio;// The following groups all produce the same output of:// 0 1 2 3 4foreach (i; 0 .. 5)        writef("%s ", i);    writeln();import std.range :iota;foreach (i;iota(0, 5))        writef("%s ", i);    writeln();    writefln("%(%s %|%)",iota(0, 5));import std.algorithm.iteration : map;import std.algorithm.mutation : copy;import std.format;iota(0, 5).map!(i => format("%s ", i)).copy(stdout.lockingTextWriter());    writeln();}

Examples:
import std.algorithm.comparison : equal;import std.math.operations : isClose;auto r =iota(0, 10, 1);assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));assert(3in r);assert(r.contains(3));//Same as aboveassert(!(10in r));assert(!(-8in r));r =iota(0, 11, 3);assert(equal(r, [0, 3, 6, 9]));writeln(r[2]);// 6assert(!(2in r));auto rf =iota(0.0, 0.5, 0.1);assert(isClose(rf, [0.0, 0.1, 0.2, 0.3, 0.4]));
enumTransverseOptions: int;
Options for theFrontTransversal andTransversal ranges (below).
Examples:
import std.algorithm.comparison : equal;import std.exception : assertThrown;auto arr = [[1, 2], [3, 4, 5]];auto r1 = arr.frontTransversal!(TransverseOptions.assumeJagged);assert(r1.equal([1, 3]));// throws on constructionassertThrown!Exception(arr.frontTransversal!(TransverseOptions.enforceNotJagged));auto r2 = arr.frontTransversal!(TransverseOptions.assumeNotJagged);assert(r2.equal([1, 3]));// either assuming or checking for equal lengths makes// the result a random access rangewriteln(r2[0]);// 1staticassert(!__traits(compiles, r1[0]));
assumeJagged
When transversed, the elements of a range of ranges are assumed to have different lengths (e.g. a jagged array).
enforceNotJagged
The transversal enforces that the elements of a range of ranges have all the same length (e.g. an array of arrays, all having the same length). Checking is done once upon construction of the transversal range.
assumeNotJagged
The transversal assumes, without verifying, that the elements of a range of ranges have all the same length. This option is useful if checking was already done from the outside of the range.
structFrontTransversal(Ror, TransverseOptions opt = TransverseOptions.assumeJagged);

FrontTransversal!(RangeOfRanges, opt)frontTransversal(TransverseOptions opt = TransverseOptions.assumeJagged, RangeOfRanges)(RangeOfRangesrr);
Given a range of ranges, iterate transversally through the first elements of each of the enclosed ranges.
Examples:
import std.algorithm.comparison : equal;int[][] x =newint[][2];x[0] = [1, 2];x[1] = [3, 4];auto ror =frontTransversal(x);assert(equal(ror, [ 1, 3 ][]));
this(RangeOfRangesinput);
Construction from an input.
enum boolempty;

@property ref autofront();

ElementTypemoveFront();

voidpopFront();
Forward range primitives.
@property FrontTransversalsave();
Duplicates thisfrontTransversal. Note that only the encapsulating range of range will be duplicated. Underlying ranges will not be duplicated.
@property ref autoback();

voidpopBack();

ElementTypemoveBack();
Bidirectional primitives. They are offered if isBidirectionalRange!RangeOfRanges.
ref autoopIndex(size_tn);

ElementTypemoveAt(size_tn);

voidopIndexAssign(ElementTypeval, size_tn);
Random-access primitive. It is offered if isRandomAccessRange!RangeOfRanges && (opt == TransverseOptions.assumeNotJagged || opt == TransverseOptions.enforceNotJagged).
typeof(this)opSlice(size_tlower, size_tupper);
Slicing if offered ifRangeOfRanges supports slicing and all the conditions for supporting indexing are met.
structTransversal(Ror, TransverseOptions opt = TransverseOptions.assumeJagged);

Transversal!(RangeOfRanges, opt)transversal(TransverseOptions opt = TransverseOptions.assumeJagged, RangeOfRanges)(RangeOfRangesrr, size_tn);
Given a range of ranges, iterate transversally through thenth element of each of the enclosed ranges. This function is similar tounzip in other languages.
Parameters:
optControls the assumptions the function makes about the lengths of the ranges
RangeOfRangesrrAn input range of random access ranges
Returns:
At minimum, an input range. Range primitives such as bidirectionality and random access are given if the element type ofrr provides them.
Examples:
import std.algorithm.comparison : equal;int[][] x =newint[][2];x[0] = [1, 2];x[1] = [3, 4];auto ror =transversal(x, 1);assert(equal(ror, [ 2, 4 ]));
Examples:
The following code does a full unzip
import std.algorithm.comparison : equal;import std.algorithm.iteration : map;int[][] y = [[1, 2, 3], [4, 5, 6]];auto z = y.front.walkLength.iota.map!(i =>transversal(y, i));assert(equal!equal(z, [[1, 4], [2, 5], [3, 6]]));
this(RangeOfRangesinput, size_tn);
Construction from an input and an index.
enum boolempty;

@property ref autofront();

EmoveFront();

@property voidfront(Eval);

voidpopFront();

@property typeof(this)save();
Forward range primitives.
@property ref autoback();

voidpopBack();

EmoveBack();

@property voidback(Eval);
Bidirectional primitives. They are offered if isBidirectionalRange!RangeOfRanges.
ref autoopIndex(size_tn);

EmoveAt(size_tn);

voidopIndexAssign(Eval, size_tn);
Random-access primitive. It is offered if isRandomAccessRange!RangeOfRanges && (opt == TransverseOptions.assumeNotJagged || opt == TransverseOptions.enforceNotJagged).
typeof(this)opSlice(size_tlower, size_tupper);
Slicing if offered ifRangeOfRanges supports slicing and all the conditions for supporting indexing are met.
Transposed!(RangeOfRanges, opt)transposed(TransverseOptions opt = TransverseOptions.assumeJagged, RangeOfRanges)(RangeOfRangesrr)
if (isForwardRange!RangeOfRanges && isInputRange!(ElementType!RangeOfRanges) && hasAssignableElements!RangeOfRanges);
Given a range of ranges, returns a range of ranges where thei'th subrangecontains thei'th elements of the original subranges.
Parameters:
optControls the assumptions the function makes about the lengths of the ranges (i.e. jagged or not)
RangeOfRangesrrRange of ranges
Examples:
import std.algorithm.comparison : equal;int[][] ror = [    [1, 2, 3],    [4, 5, 6]];auto xp =transposed(ror);assert(equal!"a.equal(b)"(xp, [    [1, 4],    [2, 5],    [3, 6]]));
Examples:
int[][] x =newint[][2];x[0] = [1, 2];x[1] = [3, 4];auto tr =transposed(x);int[][] witness = [ [ 1, 3 ], [ 2, 4 ] ];uint i;foreach (e; tr){    writeln(array(e));// witness[i++]}
structIndexed(Source, Indices) if (isRandomAccessRange!Source && isInputRange!Indices && is(typeof(Source.init[ElementType!Indices.init])));

Indexed!(Source, Indices)indexed(Source, Indices)(Sourcesource, Indicesindices);
This struct takes two ranges,source andindices, and creates a viewofsource as if its elements were reordered according toindices.indices may include only a subset of the elements ofsource andmay also repeat elements.
Source must be a random access range. The returned range will bebidirectional or random-access ifIndices is bidirectional orrandom-access, respectively.
Examples:
import std.algorithm.comparison : equal;autosource = [1, 2, 3, 4, 5];autoindices = [4, 3, 1, 2, 0, 4];auto ind =indexed(source,indices);assert(equal(ind, [5, 4, 2, 3, 1, 5]));assert(equal(retro(ind), [5, 1, 3, 2, 4, 5]));
@property ref autofront();

voidpopFront();

@property typeof(this)save();

@property ref autofront(ElementType!SourcenewVal);

automoveFront();

@property ref autoback();

voidpopBack();

@property ref autoback(ElementType!SourcenewVal);

automoveBack();

ref autoopIndex(size_tindex);

typeof(this)opSlice(size_ta, size_tb);

autoopIndexAssign(ElementType!SourcenewVal, size_tindex);

automoveAt(size_tindex);
Range primitives
@property Sourcesource();
Returns the source range.
@property Indicesindices();
Returns the indices range.
size_tphysicalIndex(size_tlogicalIndex);
Returns the physical index into the source range corresponding to a given logical index. This is useful, for example, when indexing anIndexed without adding another layer of indirection.
Examples:
auto ind = indexed([1, 2, 3, 4, 5], [1, 3, 4]);writeln(ind.physicalIndex(0));// 1
structChunks(Source) if (isInputRange!Source);

Chunks!Sourcechunks(Source)(Sourcesource, size_tchunkSize)
if (isInputRange!Source);
This range iterates over fixed-sized chunks of sizechunkSize of asource range.Source must be aninput range.chunkSize must be greater than zero.
If!isInfinite!Source andsource.walkLength is not evenlydivisible bychunkSize, the back element of this range will containfewer thanchunkSize elements.
IfSource is a forward range, the resulting range will be forward ranges aswell. Otherwise, the resulting chunks will be input ranges consuming the sameinput: iterating overfront will shrink the chunk such that subsequentinvocations offront will no longer return the full chunk, and callingpopFront on the outer range will invalidate any lingering references toprevious values offront.
Parameters:
SourcesourceRange from which the chunks will be selected
size_tchunkSizeChunk size
See Also:
Returns:
Range of chunks.
Examples:
import std.algorithm.comparison : equal;autosource = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];autochunks =chunks(source, 4);writeln(chunks[0]);// [1, 2, 3, 4]writeln(chunks[1]);// [5, 6, 7, 8]writeln(chunks[2]);// [9, 10]writeln(chunks.back);// chunks[2]writeln(chunks.front);// chunks[0]writeln(chunks.length);// 3assert(equal(retro(array(chunks)), array(retro(chunks))));
Examples:
Non-forward input ranges are supported, but with limited semantics.
import std.algorithm.comparison : equal;int i;// The generator doesn't save state, so it cannot be a forward range.auto inputRange = generate!(() => ++i).take(10);// We can still process it in chunks, but it will be single-pass only.auto chunked = inputRange.chunks(2);assert(chunked.front.equal([1, 2]));assert(chunked.front.empty);// Iterating the chunk has consumed itchunked.popFront;assert(chunked.front.equal([3, 4]));
this(Sourcesource, size_tchunkSize);
Standard constructor
@property autofront();

voidpopFront();

@property boolempty();
Input range primitives. Always present.
@property typeof(this)save();
Forward range primitives. Only present ifSource is a forward range.
@property size_tlength();
Length. Only ifhasLength!Source istrue
autoopIndex(size_tindex);

typeof(this)opSlice(size_tlower, size_tupper);
Indexing and slicing operations. Provided only ifhasSlicing!Source istrue.
@property autoback();

voidpopBack();
Bidirectional range primitives. Provided only if bothhasSlicing!Source andhasLength!Source aretrue.
structEvenChunks(Source) if (isForwardRange!Source && hasLength!Source);

EvenChunks!SourceevenChunks(Source)(Sourcesource, size_tchunkCount)
if (isForwardRange!Source && hasLength!Source);
This range splits asource range intochunkCount chunks ofapproximately equal length.Source must be a forward range withknown length.
Unlikechunks,evenChunks takes a chunk count (not size).The returned range will contain zero or moresource.length /chunkCount + 1 elements followed bysource.length / chunkCountelements. Ifsource.length < chunkCount, some chunks will be empty.
chunkCount must not be zero, unlesssource is also empty.
Examples:
import std.algorithm.comparison : equal;autosource = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];auto chunks =evenChunks(source, 3);writeln(chunks[0]);// [1, 2, 3, 4]writeln(chunks[1]);// [5, 6, 7]writeln(chunks[2]);// [8, 9, 10]
this(Sourcesource, size_tchunkCount);
Standard constructor
@property autofront();

voidpopFront();

@property boolempty();

@property typeof(this)save();
Forward range primitives. Always present.
@property size_tlength() const;
Length
autoopIndex(size_tindex);

typeof(this)opSlice(size_tlower, size_tupper);

@property autoback();

voidpopBack();
Indexing, slicing and bidirectional operations and range primitives. Provided only ifhasSlicing!Source istrue.
autoslide(Flag!"withPartial" f = Yes.withPartial, Source)(Sourcesource, size_twindowSize, size_tstepSize = 1)
if (isForwardRange!Source);
A fixed-sized sliding window iterationof sizewindowSize over asource range by a customstepSize.
TheSource range must be at least aForwardRangeand thewindowSize must be greater than zero.
ForwindowSize = 1 it splits the range into single element groups (akaunflatten)ForwindowSize = 2 it is similar tozip(source,source.save.dropOne).
Parameters:
fWhether the last element has fewer elements thanwindowSize it should be be ignored (No.withPartial) or added (Yes.withPartial)
SourcesourceRange from which the slide will be selected
size_twindowSizeSliding window size
size_tstepSizeSteps between the windows (by default 1)
Returns:
Range of all sliding windows with propagated bi-directionality, forwarding, random access, and slicing.

NoteTo avoid performance overhead,bi-directionality is only available whenstd.range.primitives.hasSlicing andstd.range.primitives.hasLength are true.

See Also:
Examples:
Iterate over ranges with windows
import std.algorithm.comparison : equal;assert([0, 1, 2, 3].slide(2).equal!equal(    [[0, 1], [1, 2], [2, 3]]));assert(5.iota.slide(3).equal!equal(    [[0, 1, 2], [1, 2, 3], [2, 3, 4]]));
Examples:
set a custom stepsize (default 1)
import std.algorithm.comparison : equal;assert(6.iota.slide(1, 2).equal!equal(    [[0], [2], [4]]));assert(6.iota.slide(2, 4).equal!equal(    [[0, 1], [4, 5]]));assert(iota(7).slide(2, 2).equal!equal(    [[0, 1], [2, 3], [4, 5], [6]]));assert(iota(12).slide(2, 4).equal!equal(    [[0, 1], [4, 5], [8, 9]]));
Examples:
Allow the last slide to have fewer elements than windowSize
import std.algorithm.comparison : equal;assert(3.iota.slide!(No.withPartial)(4).empty);assert(3.iota.slide!(Yes.withPartial)(4).equal!equal(    [[0, 1, 2]]));
Examples:
Count all the possible substrings of length 2
import std.algorithm.iteration : each;int[dstring] d;"AGAGA"d.slide!(Yes.withPartial)(2).each!(a => d[a]++);writeln(d);// ["AG"d:2, "GA"d:2]
Examples:
withPartial only has an effect if last element in the range doesn't have the full size
import std.algorithm.comparison : equal;assert(5.iota.slide!(Yes.withPartial)(3, 4).equal!equal([[0, 1, 2], [4]]));assert(6.iota.slide!(Yes.withPartial)(3, 4).equal!equal([[0, 1, 2], [4, 5]]));assert(7.iota.slide!(Yes.withPartial)(3, 4).equal!equal([[0, 1, 2], [4, 5, 6]]));assert(5.iota.slide!(No.withPartial)(3, 4).equal!equal([[0, 1, 2]]));assert(6.iota.slide!(No.withPartial)(3, 4).equal!equal([[0, 1, 2]]));assert(7.iota.slide!(No.withPartial)(3, 4).equal!equal([[0, 1, 2], [4, 5, 6]]));
autoonly(Values...)(return scope Valuesvalues)
if (!is(CommonType!Values == void));

autoonly()();
Assemblevalues into a range that carries all itselements in-situ.
Useful when a single value or multiple disconnected valuesmust be passed to an algorithm expecting a range, withouthaving to perform dynamic memory allocation.
As copying the range means copying all elements, it can besafely returned from functions. For the same reason, copyingthe returned range may be expensive for a large number of arguments.
Parameters:
Valuesvaluesthe values to assemble together
Returns:
ARandomAccessRange of the assembled values.
The returned range can be sliced. Its elements can be assigned to if every type inValues supports assignment from the range's element type.
See Also:
chain to chain ranges
Examples:
import std.algorithm.comparison : equal;import std.algorithm.iteration : filter, joiner, map;import std.algorithm.searching : findSplitBefore;import std.uni : isUpper;assert(equal(only('♡'),"♡"));writeln([1, 2, 3, 4].findSplitBefore(only(3))[0]);// [1, 2]assert(only("one","two","three").joiner(" ").equal("one two three"));string title ="The D Programming Language";assert(title    .filter!isUpper// take the upper case letters    .map!only// make each letter its own range    .joiner(".")// join the ranges together lazily    .equal("T.D.P.L"));
autoenumerate(Enumerator = size_t, Range)(Rangerange, Enumeratorstart = 0)
if (isIntegral!Enumerator && isInputRange!Range);
Iterate overrange with an attached index variable.
Each element is astd.typecons.Tuple containing the indexand the element, in that order, where the index member is namedindexand the element member is namedvalue.
The index starts atstart and is incremented by one on every iteration.

OverflowIfrange has length, then it is an error to pass a value forstart so thatstart +range.length is bigger thanEnumerator.max, thus it is ensured that overflow cannot happen.

Ifrange does not have length, andpopFront is called whenfront.index == Enumerator.max, the index will overflow and continue fromEnumerator.min.

Parameters:
Rangerangetheinput range to attach indexes to
Enumeratorstartthe number to start the index counter from
Returns:
At minimum, an input range. All other range primitives are given in the resulting range ifrange has them. The exceptions are the bidirectional primitives, which are propagated only ifrange has length.

ExampleUseful for usingforeach with an index loop variable:

import std.stdio : stdin, stdout;import std.range :enumerate;foreach (lineNum, line; stdin.byLine().enumerate(1))        stdout.writefln("line #%s: %s", lineNum, line);

Examples:
Can start enumeration from a negative position:
import std.array : assocArray;import std.range :enumerate;bool[int] aa =true.repeat(3).enumerate(-1).assocArray();assert(aa[-1]);assert(aa[0]);assert(aa[1]);
enum autoisTwoWayCompatible(alias fn, T1, T2);
Returns true iffn accepts variables of type T1 and T2 in any order. The following code should compile:
(ref T1 a,ref T2 b){  fn(a, b);  fn(b, a);}
Examples:
void func1(int a,int b);void func2(int a,float b);staticassert(isTwoWayCompatible!(func1,int,int));staticassert(isTwoWayCompatible!(func1,short,int));staticassert(!isTwoWayCompatible!(func2,int,float));void func3(refint a,refint b);staticassert(isTwoWayCompatible!(func3,int,int));staticassert(!isTwoWayCompatible!(func3,short,int));
enumSearchPolicy: int;
Policy used with the searching primitiveslowerBound, upperBound, andequalRange ofSortedRange below.
Examples:
import std.algorithm.comparison : equal;auto a = assumeSorted([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);auto p1 = a.upperBound!(SearchPolicy.binarySearch)(3);assert(p1.equal([4, 5, 6, 7, 8, 9]));auto p2 = a.lowerBound!(SearchPolicy.gallop)(4);assert(p2.equal([0, 1, 2, 3]));
linear
Searches in a linear fashion.
trot
Searches with a step that is grows linearly (1, 2, 3,...) leading to a quadratic search schedule (indexes tried are 0, 1, 3, 6, 10, 15, 21, 28,...) Once the search overshoots its target, the remaining interval is searched using binary search. The search is completed inΟ(sqrt(n)) time. Use it when you are reasonably confident that the value is around the beginning of the range.
gallop
Performs a galloping search algorithm, i.e. searches with a step that doubles every time, (1, 2, 4, 8, ...) leading to an exponential search schedule (indexes tried are 0, 1, 3, 7, 15, 31, 63,...) Once the search overshoots its target, the remaining interval is searched using binary search. A value is found inΟ(log(n)) time.
binarySearch
Searches using a classic interval halving policy. The search starts in the middle of the range, and each search step cuts the range in half. This policy finds a value inΟ(log(n)) time but is less cache friendly thangallop for large ranges. ThebinarySearch policy is used as the last step oftrot,gallop,trotBackwards, and gallopBackwards strategies.
trotBackwards
Similar totrot but starts backwards. Use it when confident that the value is around the end of the range.
gallopBackwards
Similar togallop but starts backwards. Use it when confident that the value is around the end of the range.
enumSortedRangeOptions: int;
Options forSortedRange ranges (below).
Examples:
// create a SortedRange, that's checked strictlySortedRange!(int[],"a < b",SortedRangeOptions.checkStrictly)([ 1, 3, 5, 7, 9 ]);
assumeSorted
Assume, that the range is sorted without checking.
checkStrictly
All elements of the range are checked to be sorted. The check is performed in O(n) time.
checkRoughly
Some elements of the range are checked to be sorted. For ranges with random order, this will almost surely detect, that it is not sorted. For almost sorted ranges it's more likely to fail. The checked elements are choosen in a deterministic manner, which makes this check reproducable. The check is performed in O(log(n)) time.
structSortedRange(Range, alias pred = "a < b", SortedRangeOptions opt = SortedRangeOptions.assumeSorted) if (isInputRange!Range && !isInstanceOf!(SortedRange, Range));

templateSortedRange(Range, alias pred = "a < b", SortedRangeOptions opt = SortedRangeOptions.assumeSorted) if (isInstanceOf!(SortedRange, Range))
Represents a sorted range. In addition to the regular range primitives, supports additional operations that take advantage of the ordering, such as merge and binary search. To obtain a SortedRange from an unsorted ranger, usestd.algorithm.sorting.sort which sortsr in place and returns the correspondingSortedRange. To construct aSortedRange from a ranger that is known to be already sorted, useassumeSorted.
Parameters:
Examples:
import std.algorithm.sorting : sort;auto a = [ 1, 2, 3, 42, 52, 64 ];auto r = assumeSorted(a);assert(r.contains(3));assert(!(32in r));auto r1 = sort!"a > b"(a);assert(3in r1);assert(!r1.contains(32));writeln(r1.release());// [64, 52, 42, 3, 2, 1]
Examples:
SortedRange could accept ranges weaker than random-access, but itis unable to provide interesting functionality for them. Therefore,SortedRange is currently restricted to random-access ranges.
No copy of the original range is ever made. If the underlying range ischanged concurrently with its correspondingSortedRange in waysthat break its sorted-ness,SortedRange will work erratically.
import std.algorithm.mutation : swap;auto a = [ 1, 2, 3, 42, 52, 64 ];auto r = assumeSorted(a);assert(r.contains(42));swap(a[3], a[5]);// illegal to break sortedness of original rangeassert(!r.contains(42));// passes although it shouldn't
Examples:
SortedRange can be searched with predicates that do not taketwo elements of the underlying range as arguments.
This is useful, if a range of structs is sorted by a member and youwant to search in that range by only providing a value for that member.
import std.algorithm.comparison : equal;staticstruct S {int i; }staticbool byI(A, B)(A a, B b){staticif (is(A == S))return a.i < b;elsereturn a < b.i;}auto r = assumeSorted!byI([S(1), S(2), S(3)]);auto lessThanTwo = r.lowerBound(2);assert(equal(lessThanTwo, [S(1)]));
@property boolempty();

@property autosave();

@property ref autofront();

voidpopFront();

@property ref autoback();

voidpopBack();

ref autoopIndex(size_ti);

autoopSlice(size_ta, size_tb) return scope;
Range primitives.
autorelease() return scope;
Releases the controlled range and returns it.
This does the opposite ofassumeSorted: instead of turning a range into aSortedRange, it extracts the original range back out of theSortedRange usingmove.std.algorithm.mutation.
Examples:
import std.algorithm.sorting : sort;int[3] data = [ 1, 2, 3 ];auto a = assumeSorted(data[]);writeln(a);// sort!"a < b"(data[])int[] p = a.release();writeln(p);// [1, 2, 3]
autolowerBound(SearchPolicy sp = SearchPolicy.binarySearch, V)(Vvalue)
if (isTwoWayCompatible!(predFun, ElementType!Range, V) && hasSlicing!Range);
This function uses a search with policysp to find the largest left subrange on whichpred(x, value) istrue for allx (e.g., ifpred is "less than", returns the portion of the range with elements strictly smaller thanvalue). The search schedule and its complexity are documented inSearchPolicy.
Examples:
import std.algorithm.comparison : equal;auto a = assumeSorted([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]);auto p = a.lowerBound(4);assert(equal(p, [ 0, 1, 2, 3 ]));
autoupperBound(SearchPolicy sp = SearchPolicy.binarySearch, V)(Vvalue)
if (isTwoWayCompatible!(predFun, ElementType!Range, V));
This function searches with policysp to find the largest rightsubrange on whichpred(value, x) istrue for allx(e.g., ifpred is "less than", returns the portion of the rangewith elements strictly greater thanvalue). The search scheduleand its complexity are documented inSearchPolicy.
For ranges that do not offer random access,SearchPolicy.linearis the only policy allowed (and it must be specified explicitly lest it exposesuser code to unexpected inefficiencies). For random-access searches, allpolicies are allowed, andSearchPolicy.binarySearch is the default.
Examples:
import std.algorithm.comparison : equal;auto a = assumeSorted([ 1, 2, 3, 3, 3, 4, 4, 5, 6 ]);auto p = a.upperBound(3);assert(equal(p, [4, 4, 5, 6]));
autoequalRange(V)(Vvalue)
if (isTwoWayCompatible!(predFun, ElementType!Range, V) && isRandomAccessRange!Range);
Returns the subrange containing all elementse for which both pred(e, value) andpred(value, e) evaluate tofalse (e.g., ifpred is "less than", returns the portion of the range with elements equal tovalue). Uses a classic binary search with interval halving until it finds a value that satisfies the condition, then usesSearchPolicy.gallopBackwards to find the left boundary andSearchPolicy.gallop to find the right boundary. These policies are justified by the fact that the two boundaries are likely to be near the first found value (i.e., equal ranges are relatively small). Completes the entire search inΟ(log(n)) time.
Examples:
import std.algorithm.comparison : equal;auto a = [ 1, 2, 3, 3, 3, 4, 4, 5, 6 ];auto r = a.assumeSorted.equalRange(3);assert(equal(r, [ 3, 3, 3 ]));
autotrisect(V)(Vvalue)
if (isTwoWayCompatible!(predFun, ElementType!Range, V) && isRandomAccessRange!Range && hasLength!Range);
Returns a tupler such thatr[0] is the same as the resultoflowerBound(value),r[1] is the same as the result ofequalRange(value), andr[2] is the same as the result ofupperBound(value). The call is faster than computing all threeseparately. Uses a search schedule similar toequalRange. Completes the entire search inΟ(log(n)) time.
Examples:
import std.algorithm.comparison : equal;auto a = [ 1, 2, 3, 3, 3, 4, 4, 5, 6 ];auto r = assumeSorted(a).trisect(3);assert(equal(r[0], [ 1, 2 ]));assert(equal(r[1], [ 3, 3, 3 ]));assert(equal(r[2], [ 4, 4, 5, 6 ]));
boolcontains(V)(Vvalue)
if (isRandomAccessRange!Range);
Returnstrue if and only ifvalue can be found inrange, which is assumed to be sorted. PerformsΟ(log(r.length))evaluations ofpred.
boolopBinaryRight(string op, V)(Vvalue)
if (op == "in" && isRandomAccessRange!Range);
Likecontains, but the value is specified before the range.
autogroupBy()();
Returns a range of subranges of elements that are equivalent according to thesorting relation.
autoassumeSorted(alias pred = "a < b", R)(Rr)
if (isInputRange!(Unqual!R));
Assumesr is sorted by predicatepred and returns thecorrespondingSortedRange!(pred, R) havingr as support.To check for sorted-ness atcostΟ(n), usestd.algorithm.sorting.isSorted.
Examples:
import std.algorithm.comparison : equal;int[] a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];auto p =assumeSorted(a);assert(equal(p.lowerBound(4), [0, 1, 2, 3]));assert(equal(p.lowerBound(5), [0, 1, 2, 3, 4]));assert(equal(p.lowerBound(6), [0, 1, 2, 3, 4, 5]));assert(equal(p.lowerBound(6.9), [0, 1, 2, 3, 4, 5, 6]));
structRefRange(R) if (isInputRange!R);

autorefRange(R)(R*range)
if (isInputRange!R);
Wrapper which effectively makes it possible to pass a range by reference. Both the original range and the RefRange will always have the exact same elements. Any operation done on one will affect the other. So, for instance, if it's passed to a function which would implicitly copy the original range if it were passed to it, the original range isnot copied but is consumed as if it were a reference type.

Notesave works as normal and operates on a new range, so ifsave is ever called on theRefRange, then no operations on the saved range will affect the original.

Parameters:
R*rangethe range to construct theRefRange from
Returns:
ARefRange. If the given range is a class type (and thus is already a reference type), then the original range is returned rather than aRefRange.
Examples:
Basic Example
import std.algorithm.searching : find;ubyte[] buffer = [1, 9, 45, 12, 22];auto found1 = find(buffer, 45);writeln(found1);// [45, 12, 22]writeln(buffer);// [1, 9, 45, 12, 22]auto wrapped1 =refRange(&buffer);auto found2 = find(wrapped1, 45);writeln(*found2.ptr);// [45, 12, 22]writeln(buffer);// [45, 12, 22]auto found3 = find(wrapped1.save, 22);writeln(*found3.ptr);// [22]writeln(buffer);// [45, 12, 22]string str ="hello world";auto wrappedStr =refRange(&str);writeln(str.front);// 'h'str.popFrontN(5);writeln(str);// " world"writeln(wrappedStr.front);// ' 'writeln(*wrappedStr.ptr);// " world"
Examples:
opAssign Example.
ubyte[] buffer1 = [1, 2, 3, 4, 5];ubyte[] buffer2 = [6, 7, 8, 9, 10];auto wrapped1 =refRange(&buffer1);auto wrapped2 =refRange(&buffer2);assert(wrapped1.ptris &buffer1);assert(wrapped2.ptris &buffer2);assert(wrapped1.ptr !is wrapped2.ptr);assert(buffer1 != buffer2);wrapped1 = wrapped2;//Everything points to the same stuff as before.assert(wrapped1.ptris &buffer1);assert(wrapped2.ptris &buffer2);assert(wrapped1.ptr !is wrapped2.ptr);//But buffer1 has changed due to the assignment.writeln(buffer1);// [6, 7, 8, 9, 10]writeln(buffer2);// [6, 7, 8, 9, 10]buffer2 = [11, 12, 13, 14, 15];//Everything points to the same stuff as before.assert(wrapped1.ptris &buffer1);assert(wrapped2.ptris &buffer2);assert(wrapped1.ptr !is wrapped2.ptr);//But buffer2 has changed due to the assignment.writeln(buffer1);// [6, 7, 8, 9, 10]writeln(buffer2);// [11, 12, 13, 14, 15]wrapped2 =null;//The pointer changed for wrapped2 but not wrapped1.assert(wrapped1.ptris &buffer1);assert(wrapped2.ptrisnull);assert(wrapped1.ptr !is wrapped2.ptr);//buffer2 is not affected by the assignment.writeln(buffer1);// [6, 7, 8, 9, 10]writeln(buffer2);// [11, 12, 13, 14, 15]
pure nothrow @safe this(R*range);
autoopAssign(RefRangerhs);
This does not assign the pointer ofrhs to thisRefRange. Rather it assigns the range pointed to byrhs to the range pointed to by thisRefRange. This is becauseany operation on aRefRange is the same is if it occurred to the original range. The one exception is when aRefRange is assignednull either directly or becauserhs isnull. In that case,RefRange no longer refers to the original range but isnull.
voidopAssign(typeof(null)rhs);
pure nothrow @property @safe inout(R*)ptr() inout;
A pointer to the wrapped range.
@property autofront();

@property autofront() const;

@property autofront(ElementType!Rvalue);
@property boolempty();

@property boolempty() const;
voidpopFront();
@property autosave();

@property autosave() const;

autoopSlice();

autoopSlice() const;
Only defined ifisForwardRange!R istrue.
@property autoback();

@property autoback() const;

@property autoback(ElementType!Rvalue);

voidpopBack();
Only defined ifisBidirectionalRange!R istrue.
ref autoopIndex(IndexType)(IndexTypeindex);

ref autoopIndex(IndexType)(IndexTypeindex) const;
Only defined ifisRandomAccessRange!R istrue.
automoveFront();
Only defined ifhasMobileElements!R andisForwardRange!R aretrue.
automoveBack();
Only defined ifhasMobileElements!R andisBidirectionalRange!R aretrue.
automoveAt(size_tindex);
Only defined ifhasMobileElements!R andisRandomAccessRange!R aretrue.
@property size_tlength();

@property size_tlength() const;

aliasopDollar = length;
Only defined ifhasLength!R istrue.
autoopSlice(IndexType1, IndexType2)(IndexType1begin, IndexType2end);

autoopSlice(IndexType1, IndexType2)(IndexType1begin, IndexType2end) const;
Only defined ifhasSlicing!R istrue.
autobitwise(R)(auto ref Rrange)
if (isInputRange!R && isIntegral!(ElementType!R));
Bitwise adapter over an integral type range. Consumes the range elements bit bybit, from the least significant bit to the most significant bit.
Parameters:
Ran integralinput range to iterate over
Rrangerange to consume bit by by
Returns:
ABitwise input range with propagated forward, bidirectional and random access capabilities
Examples:
import std.algorithm.comparison : equal;import std.format : format;// 00000011 00001001ubyte[] arr = [3, 9];auto r = arr.bitwise;// iterate through it as with any other rangewriteln(format("%(%d%)", r));// "1100000010010000"assert(format("%(%d%)", r.retro).equal("1100000010010000".retro));auto r2 = r[5 .. $];// set a bitr[2] = 1;writeln(arr[0]);// 7writeln(r[5]);// r2[0]
Examples:
You can use bitwise to implement an uniform bool generator
import std.algorithm.comparison : equal;import std.random : rndGen;auto rb = rndGen.bitwise;staticassert(isInfinite!(typeof(rb)));auto rb2 = rndGen.bitwise;// Don't forget that structs are passed by valueassert(rb.take(10).equal(rb2.take(10)));
structNullSink;

ref autonullSink();
An OutputRange that discards the data it receives.
Examples:
import std.algorithm.iteration : map;import std.algorithm.mutation : copy;[4, 5, 6].map!(x => x * 2).copy(nullSink);// data is discarded
Examples:
import std.csv : csvNextToken;string line ="a,b,c";// ignore the first columnline.csvNextToken(nullSink, ',', '"');line.popFront;// look at the second columnAppender!string app;line.csvNextToken(app, ',', '"');writeln(app.data);// "b"
autotee(Flag!"pipeOnPop" pipeOnPop = Yes.pipeOnPop, R1, R2)(R1inputRange, R2outputRange)
if (isInputRange!R1 && isOutputRange!(R2, ElementType!R1));

autotee(alias fun, Flag!"pipeOnPop" pipeOnPop = Yes.pipeOnPop, R1)(R1inputRange)
if (is(typeof(fun) == void) || isSomeFunction!fun);
Implements a "tee" style pipe, wrapping an input range so that elements of the range can be passed to a provided function orOutputRange as they are iterated over. This is useful for printing out intermediate values in a long chain of range code, performing some operation with side-effects on each call tofront orpopFront, or diverting the elements of a range into an auxiliaryOutputRange.
It is important to note that as the resultant range is evaluated lazily, in the case of the version oftee that takes a function, the function will not actually be executed until the range is "walked" using functions that evaluate ranges, such asstd.array.array orstd.algorithm.iteration.fold.
Parameters:
pipeOnPopIfYes.pipeOnPop, simply iterating the range without ever callingfront is enough to havetee mirror elements tooutputRange (or, respectively,fun). Note that eachpopFront() call will mirror the oldfront value, not the new one. This means that the last value will not be forwarded if the range isn't iterated until empty. IfNo.pipeOnPop, only elements for whichfront does get called will be also sent tooutputRange/fun. Iffront is called twice for the same element, it will still be sent only once. If this caching is undesired, consider usingstd.algorithm.iteration.map instead.
R1inputRangeThe input range being passed through.
R2outputRangeThis range will receive elements ofinputRange progressively as iteration proceeds.
funThis function will be called with elements ofinputRange progressively as iteration proceeds.
Returns:
An input range that offers the elements ofinputRange. Regardless of whetherinputRange is a more powerful range (forward, bidirectional etc), the result is always an input range. Reading this causesinputRange to be iterated and returns its elements in turn. In addition, the same elements will be passed tooutputRange orfun as well.
See Also:
Examples:
import std.algorithm.comparison : equal;import std.algorithm.iteration : filter, map;// Sum values while copyingint[] values = [1, 4, 9, 16, 25];int sum = 0;auto newValues = values.tee!(a => sum += a).array;assert(equal(newValues, values));writeln(sum);// 1 + 4 + 9 + 16 + 25// Count values that pass the first filterint count = 0;auto newValues4 = values.filter!(a => a < 10)                        .tee!(a => count++)                        .map!(a => a + 1)                        .filter!(a => a < 10);//Fine, equal also evaluates any lazy ranges passed to it.//count is not 3 until equal evaluates newValues4assert(equal(newValues4, [2, 5]));writeln(count);// 3
autopadLeft(R, E)(Rr, Ee, size_tn)
if ((isInputRange!R && hasLength!R || isForwardRange!R) && !is(CommonType!(ElementType!R, E) == void));
Extends the length of the input ranger by padding out the start of therange with the elemente. The elemente must be of a common type withthe element type of the ranger as defined bystd.traits.CommonType.Ifn is less than the length of ofr, thenr is returned unmodified.
Ifr is a string with Unicode characters in it,padLeft follows D's rulesabout length for strings, which is not the number of characters, orgraphemes, but instead the number of encoding units. If you want to treat eachgrapheme as only one encoding unit long, then callstd.uni.byGrapheme before calling this function.
Ifr has a length, then this isΟ(1). Otherwise, it'sΟ(r.length).
Parameters:
Rraninput range with a length, or a forward range
Eeelement to pad the range with
size_tnthe length to pad to
Returns:
A range containing the elements of the original range with the extra padding
See Also:std.string.leftJustifier
Examples:
import std.algorithm.comparison : equal;assert([1, 2, 3, 4].padLeft(0, 6).equal([0, 0, 1, 2, 3, 4]));assert([1, 2, 3, 4].padLeft(0, 3).equal([1, 2, 3, 4]));assert("abc".padLeft('_', 6).equal("___abc"));
autopadRight(R, E)(Rr, Ee, size_tn)
if (isInputRange!R && !isInfinite!R && !is(CommonType!(ElementType!R, E) == void));
Extend the length of the input ranger by padding out the end of the rangewith the elemente. The elemente must be of a common type with theelement type of the ranger as defined bystd.traits.CommonType.Ifn is less than the length of ofr, then the contents ofr arereturned.
The range primitives that the resulting range provides depends whether or notrprovides them. Except the functionsback andpopBack, which also requirethe range to have a length as well asback andpopBack
Parameters:
Rraninput range with a length
Eeelement to pad the range with
size_tnthe length to pad to
Returns:
A range containing the elements of the original range with the extra padding
See Also:std.string.rightJustifier
Examples:
import std.algorithm.comparison : equal;assert([1, 2, 3, 4].padRight(0, 6).equal([1, 2, 3, 4, 0, 0]));assert([1, 2, 3, 4].padRight(0, 4).equal([1, 2, 3, 4]));assert("abc".padRight('_', 6).equal("abc___"));
enum autoisSomeFiniteCharInputRange(R);
This simplifies a commonly used idiom in phobos for accepting any kind of stringparameter. The typeR can for example be a simple string, chained string usingstd.range.chain,std.path.chainPath or any other input range ofcharacters.
Only finite length character ranges are allowed with this constraint.
This template is equivalent to:
isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R)
See Also:
Examples:
import std.path : chainPath;import std.range : chain;void someLibraryMethod(R)(R argument)if (isSomeFiniteCharInputRange!R){// implementation detail, would iterate over each character of argument}someLibraryMethod("simple strings work");someLibraryMethod(chain("chained"," ","strings"," ","work"));someLibraryMethod(chainPath("chained","paths","work"));// you can also use custom structs implementing a char range
Copyright © 1999-2025 by theD Language Foundation | Page generated byDdoc on Fri Oct 10 22:10:52 2025

[8]ページ先頭

©2009-2025 Movatter.jp