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.algorithm.iteration

This is a submodule ofstd.algorithm.It contains generic iteration algorithms.
Cheat Sheet
Function NameDescription
cache Eagerly evaluates and caches another range'sfront.
cacheBidirectional As above, but also providesback andpopBack.
chunkBychunkBy!((a,b) => a[1] == b[1])([[1, 1], [1, 2], [2, 2], [2, 1]]) returns a range containing 3 subranges: the first with just[1, 1]; the second with the elements[1, 2] and[2, 2]; and the third with just[2, 1].
cumulativeFoldcumulativeFold!((a, b) => a + b)([1, 2, 3, 4]) returns a lazily-evaluated range containing the successive reduced values1,3,6,10.
eacheach!writeln([1, 2, 3]) eagerly prints the numbers1,2 and3 on their own lines.
filterfilter!(a => a > 0)([1, -1, 2, 0, -3]) iterates over elements1 and2.
filterBidirectional Similar tofilter, but also providesback andpopBack at a small increase in cost.
foldfold!((a, b) => a + b)([1, 2, 3, 4]) returns10.
groupgroup([5, 2, 2, 3, 3]) returns a range containing the tuplestuple(5, 1),tuple(2, 2), andtuple(3, 2).
joinerjoiner(["hello", "world!"], "; ") returns a range that iterates over the characters"hello; world!". No new string is created - the existing inputs are iterated.
mapmap!(a => a * 2)([1, 2, 3]) lazily returns a range with the numbers2,4,6.
mean Colloquially known as the average,mean([1, 2, 3]) returns2.
permutations Lazily computes all permutations using Heap's algorithm.
reducereduce!((a, b) => a + b)([1, 2, 3, 4]) returns10. This is the old implementation offold.
splitWhen Lazily splits a range by comparing adjacent elements.
splitter Lazily splits a range by a separator.
substitute[1, 2].substitute(1, 0.1) returns[0.1, 2].
sum Same asfold, but specialized for accurate summation.
uniq Iterates over the unique elements in a range, which is assumed sorted.
License:
Boost License 1.0.
Authors:
Andrei Alexandrescu

Sourcestd/algorithm/iteration.d

autocache(Range)(Rangerange)
if (isInputRange!Range);

autocacheBidirectional(Range)(Rangerange)
if (isBidirectionalRange!Range);
cache eagerly evaluatesfront ofrangeon each construction or call topopFront,to store the result in a cache.The result is then directly returned whenfront is called,rather than re-evaluated.
This can be a useful function to place in a chain, after functionsthat have expensive evaluation, as a lazy alternative tostd.array.array.In particular, it can be placed after a call tomap, or before a callstd.range.filter orstd.range.tee
cache may providebidirectional rangeiteration if needed, but since this comes at an increased cost, it must be explicitly requested via thecall tocacheBidirectional. Furthermore, a bidirectional cache willevaluate the "center" element twice, when there is only one element left inthe range.
cache does not provide random access primitives,ascache would be unable to cache the random accesses.IfRange provides slicing primitives,thencache will provide the same slicing primitives,buthasSlicing!Cache will not yield true (as thestd.range.primitives.hasSlicingtrait also checks for random access).
Parameters:
Rangerangeaninput range
Returns:
Aninput range with the cached values of range
Examples:
import std.algorithm.comparison : equal;import std.range, std.stdio;import std.typecons : tuple;ulong counter = 0;double fun(int x){    ++counter;// http://en.wikipedia.org/wiki/Quartic_functionreturn ( (x + 4.0) * (x + 1.0) * (x - 1.0) * (x - 3.0) ) / 14.0 + 0.5;}// Without cache, with array (greedy)auto result1 = iota(-4, 5).map!(a =>tuple(a, fun(a)))()                         .filter!(a => a[1] < 0)()                         .map!(a => a[0])()                         .array();// the values of x that have a negative y are:assert(equal(result1, [-3, -2, 2]));// Check how many times fun was evaluated.// As many times as the number of items in both source and result.writeln(counter);// iota(-4, 5).length + result1.lengthcounter = 0;// Without array, with cache (lazy)auto result2 = iota(-4, 5).map!(a =>tuple(a, fun(a)))()                         .cache()                         .filter!(a => a[1] < 0)()                         .map!(a => a[0])();// the values of x that have a negative y are:assert(equal(result2, [-3, -2, 2]));// Check how many times fun was evaluated.// Only as many times as the number of items in source.writeln(counter);// iota(-4, 5).length
Examples:
Tip:cache is eager when evaluating elements. If calling front on theunderlying range has a side effect, it will be observable before callingfront on the actual cached range.
Furthermore, care should be taken composingcache withstd.range.take.By placingtake beforecache, thencache will be "aware"of when the range ends, and correctly stop caching elements when needed.If calling front has no side effect though, placingtake aftercachemay yield a faster range.
Either way, the resulting ranges will be equivalent, but maybe not at thesame cost or side effects.
import std.algorithm.comparison : equal;import std.range;int i = 0;auto r = iota(0, 4).tee!((a){i = a;}, No.pipeOnPop);auto r1 = r.take(3).cache();auto r2 = r.cache().take(3);assert(equal(r1, [0, 1, 2]));assert(i == 2);//The last "seen" element was 2. The data in cache has been cleared.assert(equal(r2, [0, 1, 2]));assert(i == 3);//cache has accessed 3. It is still stored internally by cache.
templatemap(fun...) if (fun.length >= 1)
Implements the homonym function (also known astransform) presentin many languages of functional flavor. The callmap!(fun)(range)returns a range of which elements are obtained by applyingfun(a)left to right for all elementsa inrange. The original ranges arenot changed. Evaluation is done lazily.
Parameters:
funone or more transformation functions
See Also:
Examples:
import std.algorithm.comparison : equal;import std.range : chain, only;auto squares =    chain(only(1, 2, 3, 4), only(5, 6)).map!(a => a * a);assert(equal(squares, only(1, 4, 9, 16, 25, 36)));
Examples:
Multiple functions can be passed tomap. In that case, theelement type ofmap is a tuple containing one element for eachfunction.
auto sums = [2, 4, 6, 8];auto products = [1, 4, 9, 16];size_t i = 0;foreach (result; [ 1, 2, 3, 4 ].map!("a + a","a * a")){    writeln(result[0]);// sums[i]    writeln(result[1]);// products[i]    ++i;}
Examples:
You may aliasmap with some function(s) to a symbol and useit separately:
import std.algorithm.comparison : equal;import std.conv : to;alias stringize =map!(to!string);assert(equal(stringize([ 1, 2, 3, 4 ]), ["1","2","3","4" ]));
automap(Range)(Ranger)
if (isInputRange!(Unqual!Range));
Parameters:
Rangeraninput range
Returns:
A range with each fun applied to all the elements. If there is more than one fun, the element type will beTuple containing one element for each fun.
templateeach(alias fun = "a")
Eagerly iterates overr and callsfun with each element.
If no function to call is specified,each defaults to doing nothing butconsuming the entire range.r.front will be evaluated, but that can be avoidedby specifying a lambda with alazy parameter.
each also supportsopApply-based types, so it works with e.g.std.parallelism.parallel.
Normally the entire range is iterated. If partial iteration (early stopping) isdesired,fun needs to return a value of typestd.typecons.Flag!"each" (Yes.each to continue iteration, orNo.each to stopiteration).
Parameters:
funfunction to apply to each element of the range
Range rrange or iterable over whicheach iterates
Returns:
Yes.each if the entire range was iterated,No.each in case of earlystopping.
See Also:
Examples:
import std.range : iota;import std.typecons : No;int[] arr;iota(5).each!(n => arr ~= n);writeln(arr);// [0, 1, 2, 3, 4]// stop iterating earlyiota(5).each!((n) { arr ~= n;return No.each; });writeln(arr);// [0, 1, 2, 3, 4, 0]// If the range supports it, the value can be mutated in placearr.each!((ref n) => n++);writeln(arr);// [1, 2, 3, 4, 5, 1]arr.each!"a++";writeln(arr);// [2, 3, 4, 5, 6, 2]auto m = arr.map!(n => n);// by-ref lambdas are not allowed for non-ref rangesstaticassert(!__traits(compiles, m.each!((ref n) => n++)));// The default predicate consumes the range(&m).each();assert(m.empty);
Examples:
each can pass an index variable for iterable objects which support this
auto arr =new size_t[4];arr.each!"a=i"();writeln(arr);// [0, 1, 2, 3]arr.each!((i,ref e) => e = i * 2);writeln(arr);// [0, 2, 4, 6]
Examples:
opApply iterators work as well
staticclass S{int x;int opApply(scopeintdelegate(refint _x) dg) {return dg(x); }}auto s =new S;s.each!"a++";writeln(s.x);// 1
Flag!"each"each(Range)(Ranger)
if (!isForeachIterable!Range && (isRangeIterable!Range || __traits(compiles, typeof(r.front).length)));

Flag!"each"each(Iterable)(auto ref Iterabler)
if (isForeachIterable!Iterable || __traits(compiles, Parameters!(Parameters!(r.opApply))));
Parameters:
Rangerrange or iterable over which each iterates
templatefilter(alias predicate) if (is(typeof(unaryFun!predicate)))
filter!(predicate)(range) returns a new range containing only elementsx inrange forwhichpredicate(x) returnstrue.
The predicate is passed tostd.functional.unaryFun, and can be either a string, orany callable that can be executed viapred(element).
Parameters:
predicateFunction to apply to each element of range
Returns:
An input range that contains the filtered elements. Ifrange is at least a forward range, the return value offilter will also be a forward range.
See Also:
Examples:
import std.algorithm.comparison : equal;import std.math.operations : isClose;import std.range;int[] arr = [ 1, 2, 3, 4, 5 ];// Filter below 3auto small =filter!(a => a < 3)(arr);assert(equal(small, [ 1, 2 ]));// Filter again, but with Uniform Function Call Syntax (UFCS)auto sum = arr.filter!(a => a < 3);assert(equal(sum, [ 1, 2 ]));// In combination with chain() to span multiple rangesint[] a = [ 3, -2, 400 ];int[] b = [ 100, -101, 102 ];auto r = chain(a, b).filter!(a => a > 0);assert(equal(r, [ 3, 400, 100, 102 ]));// Mixing convertible types is fair game, toodouble[] c = [ 2.5, 3.0 ];auto r1 = chain(c, a, b).filter!(a =>cast(int) a != a);assert(isClose(r1, [ 2.5 ]));
autofilter(Range)(Rangerange)
if (isInputRange!(Unqual!Range));
Parameters:
RangerangeAninput range of elements
Returns:
A range containing only elementsx inrange for whichpredicate(x) returnstrue.
templatefilterBidirectional(alias pred)
Similar tofilter, except it defines abidirectional range. There is a speed disadvantage - the constructor spends time finding the last element in the range that satisfies the filtering condition (in addition to finding the first one). The advantage is that the filtered range can be spanned from both directions. Also,std.range.retro can be applied against the filtered range.
The predicate is passed tostd.functional.unaryFun, and can either accept a string, or any callable that can be executed viapred(element).
Parameters:
predFunction to apply to each element of range
Examples:
import std.algorithm.comparison : equal;import std.range;int[] arr = [ 1, 2, 3, 4, 5 ];auto small =filterBidirectional!("a < 3")(arr);staticassert(isBidirectionalRange!(typeof(small)));writeln(small.back);// 2assert(equal(small, [ 1, 2 ]));assert(equal(retro(small), [ 2, 1 ]));// In combination with chain() to span multiple rangesint[] a = [ 3, -2, 400 ];int[] b = [ 100, -101, 102 ];auto r =filterBidirectional!("a > 0")(chain(a, b));writeln(r.back);// 102
autofilterBidirectional(Range)(Ranger)
if (isBidirectionalRange!(Unqual!Range));
Parameters:
RangerBidirectional range of elements
Returns:
A range containing only the elements inr for whichpred returnstrue.
Group!(pred, Range)group(alias pred = "a == b", Range)(Ranger);

structGroup(alias pred, R) if (isInputRange!R);
Groups consecutively equivalent elements into a single tuple of the element andthe number of its repetitions.
Similarly touniq,group produces a range that iterates over uniqueconsecutive elements of the given range. Each element of this range is a tupleof the element and the number of times it is repeated in the original range.Equivalence of elements is assessed by using the predicatepred, whichdefaults to"a == b". The predicate is passed tostd.functional.binaryFun,and can either accept a string, or any callable that can be executed viapred(element, element).
Parameters:
predBinary predicate for determining equivalence of two elements.
RThe range type
RangerTheinput range to iterate over.
Returns:
A range of elements of typeTuple!(ElementType!R, uint),representing each consecutively unique element and its respective number ofoccurrences in that run. This will be an input range ifR is an inputrange, and a forward range in all other cases.
See Also:
chunkBy, which chunks an input range into subranges of equivalent adjacent elements.
Examples:
import std.algorithm.comparison : equal;import std.typecons : tuple, Tuple;int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];assert(equal(group(arr), [ tuple(1, 1u), tuple(2, 4u), tuple(3, 1u),    tuple(4, 3u), tuple(5, 1u) ][]));
Examples:
Using group, an associative array can be easily generated with the count of each unique element in the range.
import std.algorithm.sorting : sort;import std.array : assocArray;uint[string] result;auto range = ["a","b","a","c","b","c","c","d","e"];result = range.sort!((a, b) => a < b)    .group    .assocArray;writeln(result);// ["a":2U, "b":2U, "c":3U, "d":1U, "e":1U]
autochunkBy(alias pred, Range)(Ranger)
if (isInputRange!Range);
Chunks an input range into subranges of equivalent adjacent elements. In other languages this is often calledpartitionBy,groupBy orsliceWhen.
Equivalence is defined by the predicatepred, which can be either binary, which is passed tostd.functional.binaryFun, or unary, which is passed tostd.functional.unaryFun. In the binary form, two range elementsa andb are considered equivalent ifpred(a,b) is true. In unary form, two elements are considered equivalent ifpred(a) == pred(b) is true.
This predicate must be an equivalence relation, that is, it must be reflexive (pred(x,x) is always true), symmetric (pred(x,y) == pred(y,x)), and transitive (pred(x,y) && pred(y,z) impliespred(x,z)). If this is not the case, the range returned by chunkBy may assert at runtime or behave erratically. UsesplitWhen if you want to chunk by a predicate that is not an equivalence relation.
Parameters:
predPredicate for determining equivalence.
RangerAninput range to be chunked.
Returns:
With a binary predicate, a range of ranges is returned in which all elements in a given subrange are equivalent under the given predicate. With a unary predicate, a range of tuples is returned, with the tuple consisting of the result of the unary predicate for each subrange, and the subrange itself. Copying the range currently has reference semantics, but this may change in the future.

NotesEquivalent elements separated by an intervening non-equivalent element will appear in separate subranges; this function only considers adjacent equivalence. Elements in the subranges will always appear in the same order they appear in the original range.

See Also:
group, which collapses adjacent equivalent elements into a single element.
Examples:
Showing usage with binary predicate:
import std.algorithm.comparison : equal;// Grouping by particular attribute of each element:auto data = [    [1, 1],    [1, 2],    [2, 2],    [2, 3]];auto r1 = data.chunkBy!((a,b) => a[0] == b[0]);assert(r1.equal!equal([    [[1, 1], [1, 2]],    [[2, 2], [2, 3]]]));auto r2 = data.chunkBy!((a,b) => a[1] == b[1]);assert(r2.equal!equal([    [[1, 1]],    [[1, 2], [2, 2]],    [[2, 3]]]));
Examples:
Showing usage with unary predicate:
import std.algorithm.comparison : equal;import std.range.primitives;import std.typecons : tuple;// Grouping by particular attribute of each element:auto range =[    [1, 1],    [1, 1],    [1, 2],    [2, 2],    [2, 3],    [2, 3],    [3, 3]];auto byX =chunkBy!(a => a[0])(range);auto expected1 =[    tuple(1, [[1, 1], [1, 1], [1, 2]]),    tuple(2, [[2, 2], [2, 3], [2, 3]]),    tuple(3, [[3, 3]])];foreach (e; byX){assert(!expected1.empty);    writeln(e[0]);// expected1.front[0]assert(e[1].equal(expected1.front[1]));    expected1.popFront();}auto byY =chunkBy!(a => a[1])(range);auto expected2 =[    tuple(1, [[1, 1], [1, 1]]),    tuple(2, [[1, 2], [2, 2]]),    tuple(3, [[2, 3], [2, 3], [3, 3]])];foreach (e; byY){assert(!expected2.empty);    writeln(e[0]);// expected2.front[0]assert(e[1].equal(expected2.front[1]));    expected2.popFront();}
autosplitWhen(alias pred, Range)(Ranger)
if (isForwardRange!Range);
Splits a forward range into subranges in places determined by a binarypredicate.
When iterating, one element ofr is compared withpred to the nextelement. Ifpred return true, a new subrange is started for the next element.Otherwise, they are part of the same subrange.
If the elements are compared with an inequality (!=) operator, considerchunkBy instead, as it's likely faster to execute.
Parameters:
predPredicate for determining where to split. The earlier element in thesource range is always given as the first argument.
RangerAforward range to be split.
Returns:
a range of subranges ofr, split such that within a given subrange,callingpred with any pair of adjacent elements as arguments returnsfalse.Copying the range currently has reference semantics, but this may change in the future.
See Also:
splitter, which uses elements as splitters instead of element-to-elementrelations.
Examples:
import std.algorithm.comparison : equal;import std.range : dropExactly;auto source = [4, 3, 2, 11, 0, -3, -3, 5, 3, 0];auto result1 = source.splitWhen!((a,b) => a <= b);assert(result1.save.equal!equal([    [4, 3, 2],    [11, 0, -3],    [-3],    [5, 3, 0]]));//splitWhen, like chunkBy, is currently a reference range (this may change//in future). Remember to call `save` when appropriate.auto result2 = result1.dropExactly(2);assert(result1.save.equal!equal([    [-3],    [5, 3, 0]]));
autojoiner(RoR, Separator)(RoRr, Separatorsep);

autojoiner(RoR)(RoRr)
if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)));
Lazily joins a range of ranges with a separator. The separator itselfis a range. If a separator is not provided, then the ranges arejoined directly without anything in between them (often calledflattenin other languages).
Parameters:
RoRrAninput range of input ranges to be joined.
SeparatorsepAforward 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 ifboth outer and inner ranges ofRoR are at least bidirectional ranges. Else ifboth outer and inner ranges ofRoR are forward ranges, the returned range willbe likewise. Otherwise it will be only an input range. Therange bidirectionalityis propagated if no separator is specified.
See Also:
std.range.chain, which chains a sequence of ranges with compatible elementsinto a single range.

NoteWhen both outer and inner ranges ofRoR are bidirectional and the joiner isiterated from the back to the front, the separator will still be consumed fromfront to back, even if it is a bidirectional range too.

Examples:
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"));
Examples:
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"));
Examples:
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]));
Examples:
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;staticimmutable number ="12345678";staticimmutable 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;staticimmutable expected ="12,345,678";assert(formatted.equal(expected));
Examples:
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]));
templatereduce(fun...) if (fun.length >= 1)
Implements the homonym function (also known asaccumulate,compress,inject, orfoldl) present in various programminglanguages of functional flavor. There is alsofold which doesthe same thing but with the opposite parameter order.The callreduce!(fun)(seed, range) first assignsseed toan internal variableresult, also called the accumulator.Then, for each elementx inrange,result = fun(result, x)gets evaluated. Finally,result is returned.The one-argument versionreduce!(fun)(range)works similarly, but it uses the first element of the range as theseed (the range must be non-empty).
Returns:
the accumulatedresult
Parameters:
funone or more functions
See Also:
Fold (higher-order function)
fold is functionally equivalent toreduce with the argument order reversed, and without the need to usetuple for multiple seeds. This makes it easier to use in UFCS chains.
sum is similar toreduce!((a, b) => a + b) that offers pairwise summing of floating point numbers.
Examples:
Many aggregate range operations turn out to be solved withreducequickly and easily. The example below illustratesreduce'sremarkable power and flexibility.
import std.algorithm.comparison : max, min;import std.math.operations : isClose;import std.range;int[] arr = [ 1, 2, 3, 4, 5 ];// Sum all elementsauto sum =reduce!((a,b) => a + b)(0, arr);writeln(sum);// 15// Sum again, using a string predicate with "a" and "b"sum =reduce!"a + b"(0, arr);writeln(sum);// 15// Compute the maximum of all elementsauto largest =reduce!(max)(arr);writeln(largest);// 5// Max again, but with Uniform Function Call Syntax (UFCS)largest = arr.reduce!(max);writeln(largest);// 5// Compute the number of odd elementsauto odds =reduce!((a,b) => a + (b & 1))(0, arr);writeln(odds);// 3// Compute the sum of squaresauto ssquares =reduce!((a,b) => a + b * b)(0, arr);writeln(ssquares);// 55// Chain multiple ranges into seedint[] a = [ 3, 4 ];int[] b = [ 100 ];auto r =reduce!("a + b")(chain(a, b));writeln(r);// 107// Mixing convertible types is fair game, toodouble[] c = [ 2.5, 3.0 ];auto r1 =reduce!("a + b")(chain(a, b, c));assert(isClose(r1, 112.5));// To minimize nesting of parentheses, Uniform Function Call Syntax can be usedauto r2 = chain(a, b, c).reduce!("a + b");assert(isClose(r2, 112.5));
Examples:
Sometimes it is very useful to compute multiple aggregates in one pass.One advantage is that the computation is faster because the looping overheadis shared. That's whyreduce accepts multiple functions.If two or more functions are passed,reduce returns astd.typecons.Tuple object with one member per passed-in function.The number of seeds must be correspondingly increased.
import std.algorithm.comparison : max, min;import std.math.operations : isClose;import std.math.algebraic : sqrt;import std.typecons : tuple, Tuple;double[] a = [ 3.0, 4, 7, 11, 3, 2, 5 ];// Compute minimum and maximum in one passauto r =reduce!(min, max)(a);// The type of r is Tuple!(int, int)assert(isClose(r[0], 2));// minimumassert(isClose(r[1], 11));// maximum// Compute sum and sum of squares in one passr =reduce!("a + b","a + b * b")(tuple(0.0, 0.0), a);assert(isClose(r[0], 35));// sumassert(isClose(r[1], 233));// sum of squares// Compute average and standard deviation from the aboveauto avg = r[0] / a.length;writeln(avg);// 5auto stdev = sqrt(r[1] / a.length - avg * avg);writeln(cast(int)stdev);// 2
autoreduce(R)(Rr)
if (isIterable!R);
No-seed version. The first element ofr is used as the seed's value.
For each functionf infun, the corresponding seed typeS isUnqual!(typeof(f(e, e))), wheree is an element ofr:ElementType!R for ranges, andForeachType!R otherwise.
Once S has been determined, thenS s = e; ands = f(s, e); must both be legal.
Parameters:
Rran iterable value as defined byisIterable
Returns:
the final result of the accumulator applied to the iterable
Throws:
Exception ifr is empty
autoreduce(S, R)(Sseed, Rr)
if (isIterable!R);
Seed version. The seed should be a single value iffun is a single function. Iffun is multiple functions, thenseed should be astd.typecons.Tuple, with one field per function inf.
For convenience, if the seed is const, or has qualified fields, thenreduce will operate on an unqualified copy. If this happens then the returned type will not perfectly matchS.
Usefold instead ofreduce to use the seed version in a UFCS chain.
Parameters:
Sseedthe initial value of the accumulator
Rran iterable value as defined byisIterable
Returns:
the final result of the accumulator applied to the iterable
templatefold(fun...) if (fun.length >= 1)
Implements the homonym function (also known asaccumulate,compress,inject, orfoldl) present in various programminglanguages of functional flavor, iteratively calling one or more predicates.

Each predicate infun must take two arguments:

  • An accumulator value
  • An element of the ranger

Each predicate must return a value which implicitly converts to thetype of the accumulator.

For a single predicate,the callfold!(fun)(range, seed) will:

  • Useseed to initialize an internal variableresult (also called the accumulator).
  • For each elemente inrange, evaluateresult = fun(result, e).
  • Returnresult.

The one-argument versionfold!(fun)(range)works similarly, but it uses the first element of the range as theseed (the range must be non-empty) and iterates over the remainingelements.

Multiple results are produced when using multiple predicates.
Parameters:
funthe predicate function(s) to apply to the elements
See Also:
  • Fold (higher-order function)
  • sum is similar tofold!((a, b) => a + b) that offers precise summing of floating point numbers.
  • fold is functionally equivalent toreduce with the argument order reversed, and without the need to usetuple for multiple seeds.
Examples:
immutable arr = [1, 2, 3, 4, 5];// Sum all elementswriteln(arr.fold!((a, e) => a + e));// 15// Sum all elements with explicit seedwriteln(arr.fold!((a, e) => a + e)(6));// 21import std.algorithm.comparison : min, max;import std.typecons : tuple;// Compute minimum and maximum at the same timewriteln(arr.fold!(min, max));// tuple(1, 5)// Compute minimum and maximum at the same time with seedswriteln(arr.fold!(min, max)(0, 7));// tuple(0, 7)// Can be used in a UFCS chainwriteln(arr.map!(a => a + 1).fold!((a, e) => a + e));// 20// Return the last element of any rangewriteln(arr.fold!((a, e) => e));// 5
autofold(R, S...)(Rr, Sseeds);
Parameters:
Rrtheinput range to fold
Sseedsthe initial values of each accumulator (optional), one for each predicate
Returns:
Either the accumulated result for a single predicate, or aTuple of results.
templatecumulativeFold(fun...) if (fun.length >= 1)
Similar tofold, but returns a range containing the successive reduced values.The callcumulativeFold!(fun)(range, seed) first assignsseed to aninternal variableresult, also called the accumulator.The returned range contains the valuesresult = fun(result, x) lazilyevaluated for each elementx inrange. Finally, the last element has thesame value asfold!(fun)(seed, range).The one-argument versioncumulativeFold!(fun)(range) works similarly, butit returns the first element unchanged and uses it as seed for the nextelements.This function is also known aspartial_sum,accumulate,scan,Cumulative Sum.
Parameters:
funone or more functions to use as fold operation
Returns:
The function returns a range containing the consecutive reduced values. If there is more than onefun, the element type will be std.typecons.Tuple containing one element for eachfun.
See Also:

NoteIn functional programming languages this is typically calledscan,scanl,scanLeft orreductions.

Examples:
import std.algorithm.comparison : max, min;import std.array : array;import std.math.operations : isClose;import std.range : chain;int[] arr = [1, 2, 3, 4, 5];// Partial sum of all elementsauto sum =cumulativeFold!((a, b) => a + b)(arr, 0);writeln(sum.array);// [1, 3, 6, 10, 15]// Partial sum again, using a string predicate with "a" and "b"auto sum2 =cumulativeFold!"a + b"(arr, 0);writeln(sum2.array);// [1, 3, 6, 10, 15]// Compute the partial maximum of all elementsauto largest =cumulativeFold!max(arr);writeln(largest.array);// [1, 2, 3, 4, 5]// Partial max again, but with Uniform Function Call Syntax (UFCS)largest = arr.cumulativeFold!max;writeln(largest.array);// [1, 2, 3, 4, 5]// Partial count of odd elementsauto odds = arr.cumulativeFold!((a, b) => a + (b & 1))(0);writeln(odds.array);// [1, 1, 2, 2, 3]// Compute the partial sum of squaresauto ssquares = arr.cumulativeFold!((a, b) => a + b * b)(0);writeln(ssquares.array);// [1, 5, 14, 30, 55]// Chain multiple ranges into seedint[] a = [3, 4];int[] b = [100];auto r =cumulativeFold!"a + b"(chain(a, b));writeln(r.array);// [3, 7, 107]// Mixing convertible types is fair game, toodouble[] c = [2.5, 3.0];auto r1 =cumulativeFold!"a + b"(chain(a, b, c));assert(isClose(r1, [3, 7, 107, 109.5, 112.5]));// To minimize nesting of parentheses, Uniform Function Call Syntax can be usedauto r2 = chain(a, b, c).cumulativeFold!"a + b";assert(isClose(r2, [3, 7, 107, 109.5, 112.5]));
Examples:
Sometimes it is very useful to compute multiple aggregates in one pass.One advantage is that the computation is faster because the looping overheadis shared. That's whycumulativeFold accepts multiple functions.If two or more functions are passed,cumulativeFold returns astd.typecons.Tuple object with one member per passed-in function.The number of seeds must be correspondingly increased.
import std.algorithm.comparison : max, min;import std.algorithm.iteration : map;import std.math.operations : isClose;import std.typecons : tuple;double[] a = [3.0, 4, 7, 11, 3, 2, 5];// Compute minimum and maximum in one passauto r = a.cumulativeFold!(min, max);// The type of r is Tuple!(int, int)assert(isClose(r.map!"a[0]", [3, 3, 3, 3, 3, 2, 2]));// minimumassert(isClose(r.map!"a[1]", [3, 4, 7, 11, 11, 11, 11]));// maximum// Compute sum and sum of squares in one passauto r2 = a.cumulativeFold!("a + b","a + b * b")(tuple(0.0, 0.0));assert(isClose(r2.map!"a[0]", [3, 7, 14, 25, 28, 30, 35]));// sumassert(isClose(r2.map!"a[1]", [9, 25, 74, 195, 204, 208, 233]));// sum of squares
autocumulativeFold(R)(Rrange)
if (isInputRange!(Unqual!R));
No-seed version. The first element ofr is used as the seed's value. For each functionf infun, the corresponding seed typeS isUnqual!(typeof(f(e, e))), wheree is an element ofr:ElementType!R. OnceS has been determined, thenS s = e; ands = f(s, e); must both be legal.
Parameters:
RrangeAninput range
Returns:
a range containing the consecutive reduced values.
autocumulativeFold(R, S)(Rrange, Sseed)
if (isInputRange!(Unqual!R));
Seed version. The seed should be a single value iffun is a single function. Iffun is multiple functions, thenseed should be astd.typecons.Tuple, with one field per function inf. For convenience, if the seed isconst, or has qualified fields, thencumulativeFold will operate on an unqualified copy. If this happens then the returned type will not perfectly matchS.
Parameters:
RrangeAninput range
Sseedthe initial value of the accumulator
Returns:
a range containing the consecutive reduced values.
autosplitter(alias pred = "a == b", Flag!"keepSeparators" keepSeparators = No.keepSeparators, Range, Separator)(Ranger, Separators)
if (is(typeof(binaryFun!pred(r.front,s)) : bool) && (hasSlicing!Range && hasLength!Range || isNarrowString!Range));

autosplitter(alias pred = "a == b", Flag!"keepSeparators" keepSeparators = No.keepSeparators, Range, Separator)(Ranger, Separators)
if (is(typeof(binaryFun!pred(r.front,s.front)) : bool) && (hasSlicing!Range || isNarrowString!Range) && isForwardRange!Separator && (hasLength!Separator || isNarrowString!Separator));

autosplitter(alias isTerminator, Range)(Ranger)
if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(r.front))));
Lazily splits a range using an element or range as a separator.Separator ranges can be any narrow string type or sliceable range type.
Two adjacent separators are considered to surround an empty element inthe split range. Usefilter!(a => !a.empty) on the result to compressempty elements.
The predicate is passed tostd.functional.binaryFun and acceptsany callable function that can be executed viapred(element,s).

NotesIf splitting a string on whitespace and token compression is desired, consider usingsplitter without specifying a separator.

If no separator is passed, the predicateisTerminator decides whether to accept an element ofr.

Parameters:
predThe predicate for comparing each element with the separator, defaulting to"a == b".
RangerTheinput range to be split. Must support slicing and.length or be a narrow string type.
SeparatorsThe element (or range) to be treated as the separator between range segments to be split.
isTerminatorThe predicate for deciding where to split the range when no separator is passed
keepSeparatorsThe flag for deciding if the separators are kept

ConstraintsThe predicatepred needs to accept an element ofr and the separators.

Returns:
An input range of the subranges of elements between separators. Ifr is aforward range orbidirectional 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:
std.regex.splitter for a version that splits using a regular expression defined separator,std.array.split for a version that splits eagerly andsplitWhen, which compares adjacent elements instead of element against separator.
Examples:
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));
Examples:
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));
Examples:
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));
Examples:
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));
Examples:
Empty and separator-only ranges.
import std.algorithm.comparison : equal;import std.range : empty;assert("".splitter('|').empty);assert("|".splitter('|').equal(["","" ]));assert("||".splitter('|').equal(["","","" ]));
Examples:
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(["","|","","|","" ]));
Examples:
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] ]));
Examples:
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] ]));
Examples:
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]] ]));
Examples:
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]] ]));
Examples:
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]] ]));
Examples:
Leading separators, trailing separators, or no separators.
import std.algorithm.comparison : equal;assert("|ab|".splitter('|').equal(["","ab","" ]));assert("ab".splitter('|').equal(["ab" ]));
Examples:
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" ]));
Examples:
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" ]));
Examples:
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" ]));
Examples:
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!"]));
autosplitter(Range)(Ranges)
if (isSomeString!Range || isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && !isConvertibleToString!Range && isSomeChar!(ElementEncodingType!Range));
Lazily splits the character-based ranges into words, using whitespace as thedelimiter.
This function is character-range specific and, contrary tosplitter!(std.uni.isWhite), runs of whitespace will be merged together(no empty tokens will be produced).
Parameters:
RangesThe character-based range to be split. Must be a string, or a random-access range of character types.
Returns:
Aninput range of slices of the original range split by whitespace.
Examples:
import std.algorithm.comparison : equal;auto a =" a     bcd   ef gh ";assert(equal(splitter(a), ["a","bcd","ef","gh"][]));
templatesubstitute(substs...) if (substs.length >= 2 && isExpressions!substs)

autosubstitute(alias pred = (a, b) => a == b, R, Substs...)(Rr, Substssubsts)
if (isInputRange!R && (Substs.length >= 2) && !is(CommonType!Substs == void));
Returns a range with all occurrences ofsubsts inr.replaced with their substitution.
Single value replacements ('ö'.substitute!('ä', 'a', 'ö', 'o', 'ü', 'u)) aresupported as well and inΟ(1).
Parameters:
Rraninput range
Value valuea single value which can be substituted inΟ(1)
Substssubstsa set of replacements/substitutions
predthe equality function to test if element(s) are equal to a substitution
Returns:
a range with the substitutions replaced.
See Also:
std.array.replace for an eager replace algorithm orstd.string.translate, andstd.string.trfor string algorithms with translation tables.
Examples:
import std.algorithm.comparison : equal;// substitute single elementsassert("do_it".substitute('_', ' ').equal("do it"));// substitute multiple, single elementsassert("do_it".substitute('_', ' ',                           'd', 'g',                           'i', 't',                           't', 'o')              .equal("go to"));// substitute subrangesassert("do_it".substitute("_"," ","do","done")              .equal("done it"));// substitution works for any ElementTypeint[] x = [1, 2, 3];auto y = x.substitute(1, 0.1);assert(y.equal([0.1, 2, 3]));staticassert(is(typeof(y.front) ==double));import std.range : retro;assert([1, 2, 3].substitute(1, 0.1).retro.equal([3, 2, 0.1]));
Examples:
Use the faster compile-time overload
import std.algorithm.comparison : equal;// substitute subranges of a rangeassert("apple_tree".substitute!("apple","banana","tree","shrub").equal("banana_shrub"));// substitute subranges of a rangeassert("apple_tree".substitute!('a', 'b',                                't', 'f').equal("bpple_free"));// substitute valueswriteln('a'.substitute!('a', 'b', 't', 'f'));// 'b'
Examples:
Multiple substitutes
import std.algorithm.comparison : equal;import std.range.primitives : ElementType;int[3] x = [1, 2, 3];auto y = x[].substitute(1, 0.1)            .substitute(0.1, 0.2);staticassert(is(typeof(y.front) ==double));assert(y.equal([0.2, 2, 3]));auto z ="42".substitute('2', '3')             .substitute('3', '1');staticassert(is(ElementType!(typeof(z)) ==dchar));assert(equal(z,"41"));
autosubstitute(Value)(Valuevalue)
if (isInputRange!Value || !is(CommonType!(Value, typeof(substs[0])) == void));
Substitute single values with compile-time substitution mappings.

ComplexityΟ(1) due to D'sswitch guaranteeingΟ(1);

autosum(R)(Rr)
if (isInputRange!R && !isInfinite!R && is(typeof(r.front +r.front)));

autosum(R, E)(Rr, Eseed)
if (isInputRange!R && !isInfinite!R && is(typeof(seed =seed +r.front)));
Sums elements ofr, which must be a finiteinput range. Althoughconceptuallysum(r) is equivalent tofold!((a, b) => a +b)(r, 0),sum uses specialized algorithms to maximize accuracy,as follows.
For floating point inputs, calculations are made inrealprecision forreal inputs and indouble precision otherwise(Note this is a special case that deviates fromfold's behavior,which would have keptfloat precision for afloat range).For all other types, the calculations are done in the same type obtainedfrom from adding two elements of the range, which may be a differenttype from the elements themselves (for example, in case ofintegral promotion).
A seed may be passed tosum. Not only will this seed be used as an initialvalue, but its type will override all the above, and determine the algorithmand precision used for summation. If a seed is not passed, one is created withthe value oftypeof(r.front +r.front)(0), ortypeof(r.front +r.front).zeroif no constructor exists that takes an int.
Note that these specialized summing algorithms execute more primitive operationsthan vanilla summation. Therefore, if in certain cases maximum speed is requiredat expense of precision, one can usefold!((a, b) => a + b)(r, 0), whichis not specialized for summation.
Parameters:
Eseedthe initial value of the summation
Rra finite input range
Returns:
The sum of all the elements in the range r.
Examples:
Ditto
import std.range;//simple integral sumationwriteln(sum([1, 2, 3, 4]));// 10//with integral promotionwriteln(sum([false,true,true,false,true]));// 3writeln(sum(ubyte.max.repeat(100)));// 25500//The result may overflowwriteln(uint.max.repeat(3).sum());// 4294967293U//But a seed can be used to change the sumation primitivewriteln(uint.max.repeat(3).sum(ulong.init));// 12884901885UL//Floating point sumationwriteln(sum([1.0, 2.0, 3.0, 4.0]));// 10//Floating point operations have double precision minimumstaticassert(is(typeof(sum([1F, 2F, 3F, 4F])) ==double));writeln(sum([1F, 2, 3, 4]));// 10//Force pair-wise floating point sumation on large integersimport std.math.operations : isClose;assert(iota(ulong.max / 2,ulong.max / 2 + 4096).sum(0.0)           .isClose((ulong.max / 2) * 4096.0 + 4096^^2 / 2));
Tmean(T = double, R)(Rr)
if (isInputRange!R && isNumeric!(ElementType!R) && !isInfinite!R);

automean(R, T)(Rr, Tseed)
if (isInputRange!R && !isNumeric!(ElementType!R) && is(typeof(r.front +seed)) && is(typeof(r.front / size_t(1))) && !isInfinite!R);
Finds the mean (colloquially known as the average) of a range.
For built-in numerical types, accurate Knuth & Welford mean calculationis used. For user-defined types, element by element summation is used.Additionally an extra parameterseed is needed in order to correctlyseed the summation with the equivalent to0.
The first overload of this function will returnT.init if the rangeis empty. However, the second overload will returnseed on empty ranges.
This function isΟ(r.length).
Parameters:
TThe type of the return value.
RrAninput range
TseedFor user defined types. Should be equivalent to0.
Returns:
The mean ofr whenr is non-empty.
Examples:
import std.math.operations : isClose;import std.math.traits : isNaN;staticimmutable arr1 = [1, 2, 3];staticimmutable arr2 = [1.5, 2.5, 12.5];assert(arr1.mean.isClose(2));assert(arr2.mean.isClose(5.5));assert(arr1[0 .. 0].mean.isNaN);
autouniq(alias pred = "a == b", Range)(Ranger)
if (isInputRange!Range && is(typeof(binaryFun!pred(r.front,r.front)) == bool));
Lazily iterates unique consecutive elements of the given range, which isassumed to be sorted (functionality akin to theuniq systemutility). Equivalence of elements is assessed by using the predicatepred, by default"a == b". The predicate is passed tostd.functional.binaryFun, and can either accept a string, or any callablethat can be executed viapred(element, element). If the given range isbidirectional,uniq also yields abidirectional range.
Parameters:
predPredicate for determining equivalence between range elements.
RangerAninput range of elements to filter.
Returns:
Aninput range of consecutively unique elements in the original range. Ifr is also a forward range or bidirectional range, the returned range will be likewise.
Examples:
import std.algorithm.comparison : equal;import std.algorithm.mutation : copy;int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];assert(equal(uniq(arr), [ 1, 2, 3, 4, 5 ][]));// Filter duplicates in-place using copyarr.length -= arr.uniq().copy(arr).length;writeln(arr);// [1, 2, 3, 4, 5]// Note that uniqueness is only determined consecutively; duplicated// elements separated by an intervening different element will not be// eliminated:assert(equal(uniq([ 1, 1, 2, 1, 1, 3, 1]), [1, 2, 1, 3, 1]));
Permutations!Rangepermutations(Range)(Ranger);

structPermutations(Range);
Lazily computes all permutations ofr usingHeap's algorithm.
Parameters:
Rangethe range type
Rangertherandom access range to find the permutations for.
Returns:
Aforward range of elements of which are anstd.range.indexed view intor.
See Also:
Examples:
import std.algorithm.comparison : equal;import std.range : iota;assert(equal!equal(iota(3).permutations,    [[0, 1, 2],     [1, 0, 2],     [2, 0, 1],     [0, 2, 1],     [1, 2, 0],     [2, 1, 0]]));
Copyright © 1999-2025 by theD Language Foundation | Page generated byDdoc on Fri Oct 10 22:10:22 2025

[8]ページ先頭

©2009-2025 Movatter.jp