英語版
このページの英語版を見る

std.algorithm.iteration

これは std.algorithm. 一般的な反復アルゴリズムが含まれている。
チートシート
関数名 説明
cache 他の範囲のfront を評価し、キャッシュする。
cacheBidirectional 上記と同様だが、backpopBack も提供する。
chunkBy chunkBy!((a,b) => a[1] == b[1])([[1, 1], [1, 2], [2, 2], [2, 1]]) は3つのサブ範囲を含む範囲を返す。 [1, 1] 2番目は要素[1, 2][2, 2] ; そして3番目は[2, 1] だけである。
cumulativeFold cumulativeFold!((a, b) => a + b)([1, 2, 3, 4])1 を含む範囲を返す、 3 6 ,10 を返す。
each each!writeln([1, 2, 3]) は、123 をそれぞれの行に表示する。
filter filter!(a => a > 0)([1, -1, 2, 0, -3]) 要素1 および2
filterBidirectional filter に似ているが、backpopBack も提供している。 を提供する。
fold fold!((a, b) => a + b)([1, 2, 3, 4])10 を返す。
group group([5, 2, 2, 3, 3]) を含む範囲を返す。 tuple(5, 1) tuple(2, 2) tuple(3, 2) を含む範囲を返す。
joiner joiner(["hello", "world!"], "; ") を反復する範囲を返す。 "hello; world!" を反復する範囲を返す。新しい文字列は作成されない。 既存の入力が反復される。
map map!(a => a * 2)([1, 2, 3]) を含む範囲を返す。 2 4 ,6 を返す。
mean 俗に平均として知られる、mean([1, 2, 3])2 を返す。
permutations LazilyはHeapのアルゴリズムを使ってすべての順列を計算する。
reduce reduce!((a, b) => a + b)([1, 2, 3, 4])10 を返す。 これはfold の古い実装である。
splitWhen Lazily は隣接する要素を比較することで範囲を分割する。
splitter Lazily はセパレータで範囲を分割する。
substitute [1, 2].substitute(1, 0.1)[0.1, 2] を返す。
sum fold と同じだが、正確な合計のために特化されている。
uniq ソートされていると仮定された範囲内のユニークな要素を繰り返し処理する。
auto cache(Range)(Range range)
if (isInputRange!Range);

auto cacheBidirectional(Range)(Range range)
if (isBidirectionalRange!Range);
cache前を熱心に評価する。 range を評価する、 をeagerlyに評価し、結果をキャッシュに保存する。 その結果は、frontが呼ばれたときに直接返される、 が呼び出されたときに直接返される。
これは、高価な評価を必要とする関数の後に連鎖的に配置するのに便利な関数である。 の後段に置くのに便利な関数である。 std.array.array. を呼び出す前に置くことができる。 mapの呼び出しの後、あるいは std.range.filterまたは std.range.tee
cacheまたは 双方向レンジ の呼び出しによって明示的に要求する必要がある。 を呼び出して明示的に要求しなければならない。 cacheBidirectional.さらに、双方向キャッシュは は "中心 "要素を2回評価する。 を2回評価することになる。
cacheはランダムアクセスプリミティブを提供しない、 そのため cacheはランダムアクセスをキャッシュできない。 Range 、スライシング・プリミティブを提供する、 ならば cacheも同じスライシング・プリミティブを提供する、 しかし、hasSlicing!Cachestd.range.primitives.hasSlicing トレイトもランダムアクセスをチェックするからだ)。
Parameters:
Range range 入力範囲
Returns:
範囲のキャッシュ値を持つ入力範囲
Examples:
import std.algorithm.comparison : equal;
import std.range, std.stdio;
import std.typecons : tuple;

ulong counter = 0;
double fun(int x)
{
    ++counter;
    // https://ja.wikipedia.org/wiki/四次函数
    return ( (x + 4.0) * (x + 1.0) * (x - 1.0) * (x - 3.0) ) / 14.0 + 0.5;
}
// キャッシュなし、配列あり(貪欲)
auto result1 = iota(-4, 5).map!(a =>tuple(a, fun(a)))()
                         .filter!(a => a[1] < 0)()
                         .map!(a => a[0])()
                         .array();

// yが負となるxの値は次の通りである:
assert(equal(result1, [-3, -2, 2]));

// funが何回評価されたか確認する。
// ソースと結果の両方にある項目の数と同じ回数。
writeln(counter); // iota(-4, 5).length + result1.length

counter = 0;
// 配列なし、キャッシュあり(遅延)
auto result2 = iota(-4, 5).map!(a =>tuple(a, fun(a)))()
                         .cache()
                         .filter!(a => a[1] < 0)()
                         .map!(a => a[0])();

// yが負となるxの値は次の通りである:
assert(equal(result2, [-3, -2, 2]));

// funが何回評価されたか確認する。
// ソース内のアイテムの数と同じ回数だけ。
writeln(counter); // iota(-4, 5).length
Examples:
ヒント cacheは要素を評価するときにeagerである。もし を呼び出す際に副作用がある場合、キャッシュされた実際の範囲に対して を呼び出す前に観測可能となる。
さらに cachestd.range.take. の前にtakecacheの前に置くことで cacheの前に置くことで の前に置くことで、範囲がいつ終わるかを "認識 "し、必要なときに要素のキャッシュを正しく停止する。 frontを呼び出しても副作用がない場合は、takecache の後に置くと、より高速な範囲が得られるかもしれない。
いずれにせよ、結果として得られるレンジは同等になるが、同じコストや副作用ではないかもしれない。 同じコストや副作用ではないかもしれない。
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); //最後に"見た"要素は、2.キャッシュのデータがクリアされた。

assert(equal(r2, [0, 1, 2]));
assert(i == 3); //キャッシュは3にアクセスした。それは依然としてキャッシュによって内部的に保存されている。
template map(fun...) if (fun.length >= 1)
多くの関数型言語にある同音異義語関数(transform )を実装している。 を実装している。呼び出しは map!(fun)(range) を適用して得られる要素の範囲を返す。fun(a) a rangeを左から右に適用して得られる要素の範囲を返す。元の範囲は変更されない。 は変更されない。評価は遅延的に行われる。
Parameters:
fun つ以上の変換関数
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:
に複数の関数を渡すことができる。 map.その場合 の要素型はタプルになる。 mapの要素型は、各 関数ごとに1つの要素を含むタプルになる。
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:
シンボルに mapをシンボルにエイリアスして使うことができる。 を別個に使うことができる:
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" ]));
auto map(Range)(Range r)
if (isInputRange!(Unqual!Range));
Parameters:
Range r 入力範囲
Returns:
各ファンがすべての要素に適用された範囲。複数の funが複数ある場合、要素の型はTuple 、それぞれのfunに対して1つの要素が含まれる。
template each(alias fun = "a")
Eagerlyはr を繰り返し、各要素でfun を呼び出す。
呼び出す関数が指定されていない場合、 each呼び出す関数が指定されていない場合、デフォルトは何もしないが r.front が評価されるが、これは パラメータでラムダを指定することで回避できる。 lazy を指定することで回避できる。
eachopApply ベースの型もサポートしているので、例えば std.parallelism.parallel.
通常は全範囲が反復される。部分的反復(早期停止)が必要な場合 が必要な場合は、funstd.typecons.Flag!"each"(Yes.eachの値を返す必要がある。 No.eachを返す必要がある。 の値を返す必要がある。)
Parameters:
fun 範囲の各要素に適用する関数。
Range r の各要素に適用される。 eachイテレートする
Returns:
Yes.each範囲全体が反復された場合 No.each早期に 停止する。
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]

// 早めに反復をやめる
iota(5).each!((n) { arr ~= n; return No.each; });
writeln(arr); // [0, 1, 2, 3, 4, 0]

// 範囲がサポートしている場合、値をその場で変更できる
arr.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ラムダは許されない
static assert(!__traits(compiles, m.each!((ref n) => n++)));

// デフォルトの述語は範囲を消費する
(&m).each();
assert(m.empty);
Examples:
eachをサポートするイテレート可能なオブジェクトでは、インデックス変数を渡すことができる。
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イテレーターも同様に機能する
static class S
{
    int x;
    int opApply(scope int delegate(ref int _x) dg) { return dg(x); }
}

auto s = new S;
s.each!"a++";
writeln(s.x); // 1
Flag!"each" each(Range)(Range r)
if (!isForeachIterable!Range && (isRangeIterable!Range || __traits(compiles, typeof(r.front).length)));

Flag!"each" each(Iterable)(auto ref Iterable r)
if (isForeachIterable!Iterable || __traits(compiles, Parameters!(Parameters!(r.opApply))));
Parameters:
Range r それぞれが反復する範囲または反復可能範囲
template filter(alias predicate) if (is(typeof(unaryFun!predicate)))
filter!(predicate)(range)は、range の要素x のみを含む新しい範囲を返す。 に対して、predicate(x)true を返す。
述語は std.functional.unaryFunに渡され、文字列または pred(element) を介して実行可能な任意の callable である。
Parameters:
predicate 範囲の各要素に適用する関数".
Returns:
フィルタリングされた要素を含む入力範囲。range 、少なくとも前方範囲であれば filter の返り値も前方範囲になる。
Examples:
import std.algorithm.comparison : equal;
import std.math.operations : isClose;
import std.range;

int[] arr = [ 1, 2, 3, 4, 5 ];

// 3以下をフィルタする
auto small = filter!(a => a < 3)(arr);
assert(equal(small, [ 1, 2 ]));

// 統一関数呼び出し構文(UFCS)で再度フィルタリングする
auto sum = arr.filter!(a => a < 3);
assert(equal(sum, [ 1, 2 ]));

// chain()と組み合わせて複数の範囲にまたがるようにする
int[] 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 ]));

// 変換可能な型を混在させることも可能である
double[] c = [ 2.5, 3.0 ];
auto r1 = chain(c, a, b).filter!(a => cast(int) a != a);
assert(isClose(r1, [ 2.5 ]));
auto filter(Range)(Range range)
if (isInputRange!(Unqual!Range));
Parameters:
Range range 要素の入力範囲 要素の
Returns:
x の要素のみを含む範囲。 rangeの要素のみを含む範囲。 で、predicate(x)true を返す。
template filterBidirectional(alias pred)
filter と似ている。 に似ている。 コンストラクタは、フィルタリングを満たす範囲の最後の要素を見つけるのに時間を費やす。 を満たす範囲の最後の要素を見つけるのに時間がかかる。 を満たす範囲の最後の要素を見つけるのに時間がかかる。利点は フィルタリングされた範囲が両方向からスパンできることである。また std.range.retroを適用することもできる。
述語は std.functional.unaryFunに渡される。 に渡され、文字列か、pred(element) を介して実行できる任意の callable を受け取ることができる。
Parameters:
pred 範囲の各要素に適用する関数".
Examples:
import std.algorithm.comparison : equal;
import std.range;

int[] arr = [ 1, 2, 3, 4, 5 ];
auto small = filterBidirectional!("a < 3")(arr);
static assert(isBidirectionalRange!(typeof(small)));
writeln(small.back); // 2
assert(equal(small, [ 1, 2 ]));
assert(equal(retro(small), [ 2, 1 ]));
// chain()との組み合わせで複数の範囲にまたがる
int[] a = [ 3, -2, 400 ];
int[] b = [ 100, -101, 102 ];
auto r = filterBidirectional!("a > 0")(chain(a, b));
writeln(r.back); // 102
auto filterBidirectional(Range)(Range r)
if (isBidirectionalRange!(Unqual!Range));
Parameters:
Range r エレメントの双方向範囲
Returns:
の要素のみを含む範囲。 rの要素のみを含む範囲。predtrue を返す。
Group!(pred, Range) group(alias pred = "a == b", Range)(Range r);

struct Group(alias pred, R) if (isInputRange!R);
連続的に等価な要素を、要素とその繰り返し数の1つのタプルにグループ化する。 のタプルにグループ化する。
uniq と同様である、 groupは、与えられた範囲の一意な連続要素を反復する範囲を生成する。 を反復する範囲を生成する。この範囲の各要素は、要素 のタプルである。 要素の等価性は、述語pred を用いて評価される。 "a == b"に渡される。 std.functional.binaryFun, に渡され、文字列か、あるいは pred(element, element).
Parameters:
pred 2つの要素の等価性を判定する2値述語。
R 範囲型
Range r 入力範囲を を反復する。
Returns:
Tuple!(ElementType!R, uint) 型の要素の範囲、 型の要素の範囲である。 型の要素の範囲。 これは、R が入力範囲である場合は入力範囲となる。 である場合は入力範囲となり、それ以外の場合は前方範囲となる。
See Also:
chunkBy入力範囲を隣接する等価な要素に分割する。 に分割する。
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:
groupを使えば、範囲内の一意な各要素のカウントを持つ連想配列を簡単に生成できる。 を持つ連想配列を簡単に生成できる。
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]
auto chunkBy(alias pred, Range)(Range r)
if (isInputRange!Range);
入力範囲を、等価な隣接要素の部分範囲に分割する。 他の言語では、これはしばしばpartitionBy と呼ばれる、groupBy またはsliceWhen と呼ばれる。
等価性は述語pred で定義される。 に渡される。 std.functional.binaryFunに渡されるバイナリか に渡される。 std.functional.unaryFun.に渡される単項式である。 ab は、pred(a,b) が真であれば等価とみなされる。単項式では が真の場合、2つの要素は等価とみなされる。pred(a) == pred(b) が真の場合、2つの要素は等価とみなされる。
この述語は同値関係でなければならない。 反射的 (pred(x,x) は常に真である)、対称的 (pred(x,y) == pred(y,x))、他動的(pred(x,y) && pred(y,z)pred(x,z))でなければならない。そうでない場合、チャンクバイが返す範囲は、実行時にアサートされる可能性がある。 が返す範囲は、実行時にアサートされたり、挙動がおかしくなったりする。使用方法 splitWhen を使用する。
Parameters:
pred 等価性を判断するための述語。
Range r チャンクされる入力範囲
Returns:
バイナリ述語では、以下のような範囲が返される。 与えられた部分範囲のすべての要素は、与えられた述語の下で等価である。 単項述語では、タプルの範囲が返される。 タプルは、各サブレンジに対する単項述語の結果と タプルが返される。現在、範囲のコピーは参照セマンティクスを持つが、これは将来変更される可能性がある。 将来変更されるかもしれない。

注釈 非等価要素によって区切られた等価要素は、別々のサブ範囲に表示される。 この"関数"は隣接する等価要素のみを考慮する。 のみを考慮する。この関数は隣接する等価要素のみを考慮する。 で表示される。

See Also:
groupこれは、隣接する等価要素を1つの要素に折りたたむものである。 要素に折りたたむ。
Examples:
二項述語を使った用法を示す:
import std.algorithm.comparison : equal;

// 各要素の特定の属性でグループ化する:
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:
単項述語を使った用法を示す:
import std.algorithm.comparison : equal;
import std.range.primitives;
import std.typecons : tuple;

// 各要素の特定の属性でグループ化する:
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();
}
auto splitWhen(alias pred, Range)(Range r)
if (isForwardRange!Range);
バイナリ述語によって決定される場所で、前方範囲をサブ範囲に分割する。 述語によって決定される場所でサブ範囲に分割する。
反復するとき rの1つの要素は、pred と比較される。 要素と比較される。もしpred が真を返せば、次の要素に対して新しい部分範囲が開始される。 そうでなければ、それらは同じ部分範囲の一部である。
要素が不等号(!=)演算子で比較される場合は、次のように考える。 chunkByその方が実行速度が速いだろうからである。
Parameters:
pred どこで分割するかを決定するための述語。の最初の要素が常に最初の引数として与えられる。 が常に最初の引数として与えられる。
Range r 分割される前方範囲
Returns:
のサブレンジの範囲。 rの部分範囲の範囲であり、与えられた部分範囲内で分割される、 隣接する要素の任意のペアを引数としてpred を呼び出すと、false が返される。 範囲のコピーは現在参照セマンティクスを持つが、これは将来変更される可能性がある。
See Also:
splitterこれは要素間の関係ではなく、要素をスプリッターとして使用する。 関係を使用する。
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は、chunkByと同様に、現在は参照範囲である(将来的に
//変更される可能性がある)。適切なタイミングで`save`を呼び出すことを忘れないように。
auto result2 = result1.dropExactly(2);
assert(result1.save.equal!equal([
    [-3],
    [5, 3, 0]
]));
auto joiner(RoR, Separator)(RoR r, Separator sep);

auto joiner(RoR)(RoR r)
if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)));
セパレータで範囲の範囲を緩やかに結合する。セパレータ自体 は範囲である。セパレータが指定されない場合、範囲は と呼ばれる)。flatten と呼ばれる)。
Parameters:
RoR r 入力範囲 入力範囲。
Separator sep 前方範囲の 要素の前方範囲。
Returns:
結合範囲内の要素の範囲。以下の場合は双方向範囲となる。 RoR の外側範囲と内側範囲の両方が少なくとも双方向範囲であれば、これは双方向範囲となる。もし RoR の外側と内側の両方の範囲が少なくとも双方向範囲であれば、これは双方向範囲となる。 も同様である。そうでない場合は、単なる入力範囲となる。この 範囲の双方向性 は、セパレータが指定されなければ伝播される。
See Also:
std.range.chainこれは、互換性のある要素を持つ一連の範囲を1つの範囲に連結するものである。 を1つの範囲に連結する。

注釈: RoR 、外側と内側の両方の範囲が双方向であり、ジョイナーが後ろから前に反復される場合、セパレーターは後ろから前に消費される。 が後方から前方へ反復される場合、セパレータは前方から後方へ消費される。 を消費する。

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:
ジョイナーはインプレース変異を可能にする!
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:
文字列の中に文字をゆったりと挿入する
import std.algorithm.comparison : equal;
import std.range : chain, cycle, iota, only, retro, take, zip;
import std.format : format;

static immutable number = "12345678";
static immutable delimiter = ",";
auto formatted = number.retro
    .zip(3.iota.cycle.take(number.length))
    .map!(z => chain(z[0].only, z[1] == 2 ? delimiter : null))
    .joiner
    .retro;
static immutable expected = "12,345,678";
assert(formatted.equal(expected));
Examples:
ジョイナーは双方向に使用できる
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]));
template reduce(fun...) if (fun.length >= 1)
様々な関数型言語に存在する同音異義語関数(accumulatecompressinjectfoldl としても知られている)を実装している。 を実装している。また foldもある。 もあるが、これはパラメータの順序が逆である。 呼び出しは reduce!(fun)(seed, range)呼び出しは、まずseed を を内部変数result に代入する。 次に、range の各要素x が評価される、result = fun(result, x) の各要素が評価される。最後に、result が返される。 引数1つのバージョン reduce!(fun)(range) は同様に動作するが、範囲の最初の要素をシードとして使用する(範囲は空であってはならない)。 として使用する(範囲は空であってはならない)。
Returns:
累積されたresult
Parameters:
fun 一つ以上の関数
See Also:
フォールド(高次関数)
foldと関数的には等価である。 reduceに相当する。 を使う必要がない。 tuple を使う必要がない。これにより、UFCSチェーンでの使用が容易になる。
sumreduce!((a, b) => a + b)に似ている。 に似ている。
Examples:
多くの範囲演算は reduce を使って素早く簡単に解くことができる。以下の例では、以下のようになる。 reduce's の驚くべきパワーと柔軟性を示している。
import std.algorithm.comparison : max, min;
import std.math.operations : isClose;
import std.range;

int[] arr = [ 1, 2, 3, 4, 5 ];
// すべての要素を合計する
auto sum = reduce!((a,b) => a + b)(0, arr);
writeln(sum); // 15

// "a"と"b"の文字列述語を使って再度合計する
sum = reduce!"a + b"(0, arr);
writeln(sum); // 15

// すべての要素の最大値を計算する
auto largest = reduce!(max)(arr);
writeln(largest); // 5

// 再び最大値を計算するが、統一関数呼び出し構文(UFCS)を使用する
largest = arr.reduce!(max);
writeln(largest); // 5

// 奇数要素の数を計算する
auto odds = reduce!((a,b) => a + (b & 1))(0, arr);
writeln(odds); // 3

// 平方和を計算する
auto ssquares = reduce!((a,b) => a + b * b)(0, arr);
writeln(ssquares); // 55

// 複数の範囲をシードに連結する
int[] a = [ 3, 4 ];
int[] b = [ 100 ];
auto r = reduce!("a + b")(chain(a, b));
writeln(r); // 107

// 変換可能な型を混在させることも可能である
double[] c = [ 2.5, 3.0 ];
auto r1 = reduce!("a + b")(chain(a, b, c));
assert(isClose(r1, 112.5));

// 括弧の入れ子を最小限にするために、統一関数呼び出し構文を使うことができる
auto r2 = chain(a, b, c).reduce!("a + b");
assert(isClose(r2, 112.5));
Examples:
時には、1回のパスで複数の集約を計算することは非常に便利である。 一つの利点は、ループのオーバーヘッドが共有されるため、計算が速くなることである。 が共有される。これが reduceは複数の関数を受け付ける。 2つ以上の関数が渡されると reduceを返す。 std.typecons.Tupleオブジェクトを返す。 それに応じてシードの数も増やさなければならない。
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 ];
// 最小値と最大値を一度に計算する
auto r = reduce!(min, max)(a);
// rの型はTuple!(int, int)である
assert(isClose(r[0], 2));  // 最小
assert(isClose(r[1], 11)); // 最大

// 和と平方和を一度に計算する
r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a);
assert(isClose(r[0], 35));  // 和
assert(isClose(r[1], 233)); // 平方和
// 上記から平均と標準偏差を計算する
auto avg = r[0] / a.length;
writeln(avg); // 5
auto stdev = sqrt(r[1] / a.length - avg * avg);
writeln(cast(int)stdev); // 2
auto reduce(R)(R r)
if (isIterable!R);
ノーシードバージョン。の最初の要素がシードの値として使われる。 rの最初の要素がシードの値として使われる。
fun の各関数f に対して、対応するシード型 は である。 S e 、対応するシード型はUnqual!(typeof(f(e, e))) である。 の要素である。 rElementType!R である、 ForeachType!R の要素である。
Sが決まれば、S s = e;s = f(s, e); の両方が合法でなければならない。
Parameters:
R r で定義される反復可能な値である。isIterable
Returns:
で定義される反復可能な値。
Throws:
Exception もし rが空の場合
auto reduce(S, R)(S seed, R r)
if (isIterable!R);
シードのバージョン。fun 、シードは単一値でなければならない。 である場合、シードは単一の値でなければならない。fun が複数関数の場合は、次のようになる。 seed でなければならない。 std.typecons.Tupleでなければならない。f の関数ごとにフィールドが1つずつある。
便宜上、シードがconstの場合、または修飾フィールドを持つ場合は、次のようにする。 reduceは修飾されていないコピーを操作する。この場合 の場合、返される型はS と完全には一致しない。
の代わりにfold を使う。 reduceを使う。
Parameters:
S seed アキュムレータの初期値
R r で定義される反復可能な値である。isIterable
Returns:
アキュムレータの最終結果を反復可能な値に適用する。
template fold(fun...) if (fun.length >= 1)
様々な関数型言語に存在する同音異義語関数(accumulatecompressinjectfoldl としても知られている)を実装する。 を実装し、1つ以上の述語を繰り返し呼び出す。

fun の各述語は2つの引数を取らなければならない:

  • アキュムレータ値
  • 範囲の要素r

各述語は、暗黙のうちにアキュムレータの型に変換する値を返さなければならない。 型に暗黙的に変換する値を返さなければならない。

単一の述語に対して 呼び出しは fold!(fun)(range, seed)となる:

  • seed 、内部変数result (アキュムレーターとも呼ばれる)を初期化する。 を初期化する。)
  • range の各要素e に対して、result = fun(result, e) を評価する。
  • result を返す。

1引数バージョン fold!(fun)(range) は同様に動作するが、範囲の最初の要素を として使用し(範囲は空であってはならない)、残りの 要素を反復処理する。

複数の述語を使用すると、複数の結果が生成される。
Parameters:
fun 要素に適用する述語関数。
See Also:
  • 折りたたむ(高階関数)
  • sumfold!((a, b) => a + b)に似ている。 に似ている。
  • foldと関数的には等価である。 reduceと機能的に等価である。 を使う必要がない。 tuple を使う必要がない。
Examples:
immutable arr = [1, 2, 3, 4, 5];

// すべての要素を合計する
writeln(arr.fold!((a, e) => a + e)); // 15

// すべての要素を明示的なシードで合計する
writeln(arr.fold!((a, e) => a + e)(6)); // 21

import std.algorithm.comparison : min, max;
import std.typecons : tuple;

// 最小値と最大値を同時に計算する
writeln(arr.fold!(min, max)); // tuple(1, 5)

// シードを使って最小値と最大値を同時に計算する
writeln(arr.fold!(min, max)(0, 7)); // tuple(0, 7)

// UFCSチェーンで使用できる
writeln(arr.map!(a => a + 1).fold!((a, e) => a + e)); // 20

// 任意の範囲の最後の要素を返す
writeln(arr.fold!((a, e) => e)); // 5
auto fold(R, S...)(R r, S seeds);
Parameters:
R r 折りたたむ入力範囲
S seeds 各アキュムレータの初期値(オプション)。
Returns:
単一の述語に対する累積結果、または Tupleのどちらかである。
template cumulativeFold(fun...) if (fun.length >= 1)
fold に似ているが、連続する削減値を含む範囲を返す。 この呼び出しは cumulativeFold!(fun)(range, seed)呼び出しは、まずseed を内部変数 resultに代入する。 返される範囲には、result = fun(result, x) の各要素 に対して遅延評価された値 が含まれる。 rangeの各要素x に対して評価された値が含まれる。最後に、最後の要素は fold!(fun)(seed, range) と同じ値を持つ。 引数1つのバージョン cumulativeFold!(fun)(range)も同様に動作するが の各要素が評価される。 要素のシードとして使用する。 この関数は次のようにも知られている。 としても知られている、 accumulateとしても知られている、 スキャンとも呼ばれる、 累積和
Parameters:
fun 折りたたみ演算として使用する1つ以上の関数
Returns:
この関数は、連続する縮小値を含む範囲を返す。もし fun が複数ある場合、要素型は次のようになる。 std.typecons.Tuplefunになる。

注釈:」である。 関数型プログラミング言語では、これは通常scanscanl と呼ばれる、 scanLeft またはreductions と呼ばれる。

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];
// すべての要素の部分和を返す
auto sum = cumulativeFold!((a, b) => a + b)(arr, 0);
writeln(sum.array); // [1, 3, 6, 10, 15]

// "a"と"b"の文字列述語を使って、再び部分和を返す
auto sum2 = cumulativeFold!"a + b"(arr, 0);
writeln(sum2.array); // [1, 3, 6, 10, 15]

// 全要素の部分最大値を計算する
auto largest = cumulativeFold!max(arr);
writeln(largest.array); // [1, 2, 3, 4, 5]

// 再び部分最大値を計算するが、統一関数呼び出し構文(UFCS)を使用する
largest = arr.cumulativeFold!max;
writeln(largest.array); // [1, 2, 3, 4, 5]

// 奇数要素の部分カウント
auto odds = arr.cumulativeFold!((a, b) => a + (b & 1))(0);
writeln(odds.array); // [1, 1, 2, 2, 3]

// 平方部分和を計算する
auto ssquares = arr.cumulativeFold!((a, b) => a + b * b)(0);
writeln(ssquares.array); // [1, 5, 14, 30, 55]

// 複数の範囲をシードに連結する
int[] a = [3, 4];
int[] b = [100];
auto r = cumulativeFold!"a + b"(chain(a, b));
writeln(r.array); // [3, 7, 107]

// 変換可能な型を混在させることも可能である
double[] c = [2.5, 3.0];
auto r1 = cumulativeFold!"a + b"(chain(a, b, c));
assert(isClose(r1, [3, 7, 107, 109.5, 112.5]));

// 括弧の入れ子を最小限にするために、統一関数呼び出し構文を使うことができる
auto r2 = chain(a, b, c).cumulativeFold!"a + b";
assert(isClose(r2, [3, 7, 107, 109.5, 112.5]));
Examples:
時には、1回のパスで複数の集約を計算することは非常に便利である。 一つの利点は、ループのオーバーヘッドが共有されるため、計算が速くなることである。 が共有される。これが cumulativeFoldは複数の関数を受け付ける。 2つ以上の関数が渡されると cumulativeFoldを返す。 std.typecons.Tupleオブジェクトを返す。 それに応じてシードの数も増やさなければならない。
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];
// 最小値と最大値を一度に計算する
auto r = a.cumulativeFold!(min, max);
// rの型はTuple!(int, int)である
assert(isClose(r.map!"a[0]", [3, 3, 3, 3, 3, 2, 2]));     // 最小
assert(isClose(r.map!"a[1]", [3, 4, 7, 11, 11, 11, 11])); // 最大

// 和と平方和を一度に計算する
auto 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]));      // 和
assert(isClose(r2.map!"a[1]", [9, 25, 74, 195, 204, 208, 233])); // 平方和
auto cumulativeFold(R)(R range)
if (isInputRange!(Unqual!R));
シードなしバージョン。r の最初の要素がシードの値として使われる。 fun の各関数f に対して、対応するシード型S は以下の通りである。 Unqual!(typeof(f(e, e))) ここで、er の要素である: ElementType!R. S が決定されたら、S s = e;s = f(s, e); は両方とも合法でなければならない。 は両方とも合法でなければならない。
Parameters:
R range 入力範囲
Returns:
連続した縮小値を含む範囲。
auto cumulativeFold(R, S)(R range, S seed)
if (isInputRange!(Unqual!R));
シードのバージョン。fun が単一関数の場合、シードは単一値でなければならない。 は単一の値でなければならない。fun 、複数関数の場合は seedでなければならない。 std.typecons.Tupleでなければならない。f の関数ごとにフィールドが1つずつある。 便宜上、シードがconst 、または修飾されたフィールドを持つ場合は、次のようにする。 cumulativeFoldは修飾されていないコピーを操作する。この場合 の場合、返される型はS と完全には一致しない。
Parameters:
R range 入力範囲
S seed アキュムレータの初期値
Returns:
連続した減少値を含む範囲。
auto splitter(alias pred = "a == b", Flag!"keepSeparators" keepSeparators = No.keepSeparators, Range, Separator)(Range r, Separator s)
if (is(typeof(binaryFun!pred(r.front, s)) : bool) && (hasSlicing!Range && hasLength!Range || isNarrowString!Range));

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

auto splitter(alias isTerminator, Range)(Range r)
if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(r.front))));
Lazily は、要素または範囲をセパレータとして使用して範囲を分割する。 セパレータの範囲は、任意の狭い文字列型やスライス可能な範囲型にすることができる。
隣接する2つのセパレータは、分割範囲内の空の要素を囲むとみなされる。 を囲むとみなされる。空の要素を圧縮するには、結果にfilter!(a => !a.empty) を使用する。 を使用する。
述語は std.functional.binaryFunに渡され を介して実行される呼び出し可能な関数を受け取る。 pred(element, s).

注釈 文字列を空白で分割し、トークンを圧縮したい場合は 区切り文字を指定せずに splitterを使うことを検討すること。

セパレータが渡されない場合 isTerminator の要素を受け入れるかどうかを決定する。 r.

Parameters:
pred 各要素をセパレータと比較するための述語、 デフォルトは"a == b" である。
Range r 分割する入力範囲 分割される入力範囲。スライスと.length をサポートするか、狭い文字列型でなければならない。
Separator s 分割される範囲セグメント間のセパレータとして扱われる要素(または範囲)。 分割される範囲セグメント間の区切りとして扱われる要素(または範囲)。
isTerminator セパレータが渡されない場合に、範囲をどこで分割するかを決定するための述語。
keepSeparators セパレータを保持するかどうかを決定するフラグ。

制約 述語predrの要素と セパレータ s.

Returns:
セパレーター間の要素のサブレンジの入力範囲。もし r前方範囲 または双方向範囲であれば も同様になる。 範囲がセパレータとして使われている場合、双方向は不可能である。
keepSeparatorsがYes.keepSeparatorsに等しい場合、出力にはセパレータも含まれる。 を含む。
空の範囲が指定された場合、結果は空の範囲となる。もし が与えられた場合、結果は2つの空の要素を持つ範囲となる。
See Also:
std.regex.splitter正規表現で定義されたセパレーターを使って分割するバージョンについては、こちらを参照のこと、 std.array.splitを使って分割するバージョンには splitWhenは、セパレータに対する要素の代わりに隣接する要素を比較する。
Examples:
文字と数字による基本的な分割。
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:
文字と数字を使った基本的なスプリットと、センチネルをキープする。
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:
隣接するセパレーター。
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:
隣接するセパレーターと歩哨を守る。
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:
空とセパレータのみの範囲。
import std.algorithm.comparison : equal;
import std.range : empty;

assert("".splitter('|').empty);
assert("|".splitter('|').equal([ "", "" ]));
assert("||".splitter('|').equal([ "", "", "" ]));
Examples:
射撃場を空にしてセパレーターだけにし、歩哨を配置する。
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:
分割に範囲を使う
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:
分割に範囲を使う
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:
カスタム述語関数。
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:
カスタム述語関数。
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:
セパレーターなしでスプリッターを使用する
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:
先頭のセパレータ、末尾のセパレータ、またはセパレータなし。
import std.algorithm.comparison : equal;

assert("|ab|".splitter('|').equal([ "", "ab", "" ]));
assert("ab".splitter('|').equal([ "ab" ]));
Examples:
先頭のセパレータ、末尾のセパレータ、またはセパレータなし。
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:
スプリッターは、区切り文字が単一要素の場合、双方向の範囲を返す。
import std.algorithm.comparison : equal;
import std.range : retro;
assert("a|bc|def".splitter('|').retro.equal([ "def", "bc", "a" ]));
Examples:
スプリッターは、区切り文字が単一要素の場合、双方向の範囲を返す。
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:
単語でダラダラと分割する
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!"]));
auto splitter(Range)(Range s)
if (isSomeString!Range || isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && !isConvertibleToString!Range && isSomeChar!(ElementEncodingType!Range));
文字ベースの範囲 s空白を区切り文字として で区切る。
この関数は文字範囲に特化したもので、以下の関数とは異なる。 splitter!(std.uni.isWhite)とは異なり、空白を含む単語はマージされる (空トークンは生成されない)。
Parameters:
Range s 分割する文字ベースの範囲。文字列、または ランダムアクセス可能な文字型の範囲でなければならない。
Returns:
入力範囲は のスライスの入力範囲。
Examples:
import std.algorithm.comparison : equal;
auto a = " a     bcd   ef gh ";
assert(equal(splitter(a), ["a", "bcd", "ef", "gh"][]));
template substitute(substs...) if (substs.length >= 2 && isExpressions!substs)

auto substitute(alias pred = (a, b) => a == b, R, Substs...)(R r, Substs substs)
if (isInputRange!R && (Substs.length >= 2) && !is(CommonType!Substs == void));
が出現するすべての範囲を返す。 substsが出現する r. が置換された範囲を返す。
単一値置換('ö'.substitute!('ä', 'a', 'ö', 'o', 'ü', 'u))もサポートされている。 1もサポートされている
Parameters:
R r 入力範囲
Value value Ο(1) に代入できる単一の値。
Substs substs 置換/代入の集合
pred 要素(複数可)が等しいかどうかをテストする等号関数。 置換
Returns:
置換を置き換えた範囲
See Also:
std.array.replaceを使用する。 std.string.translateそして std.string.tr は変換テーブルを持つ文字列アルゴリズムである。
Examples:
import std.algorithm.comparison : equal;

// 単一要素を置換する
assert("do_it".substitute('_', ' ').equal("do it"));

// 複数の単一要素を代入する
assert("do_it".substitute('_', ' ',
                           'd', 'g',
                           'i', 't',
                           't', 'o')
              .equal("go to"));

// 部分範囲の置換
assert("do_it".substitute("_", " ",
                          "do", "done")
              .equal("done it"));

// 置換はどのElementTypeに対しても機能する
int[] x = [1, 2, 3];
auto y = x.substitute(1, 0.1);
assert(y.equal([0.1, 2, 3]));
static assert(is(typeof(y.front) == double));

import std.range : retro;
assert([1, 2, 3].substitute(1, 0.1).retro.equal([3, 2, 0.1]));
Examples:
より高速なコンパイル時オーバーロードを使用する
import std.algorithm.comparison : equal;

// 範囲の部分範囲を置換する
assert("apple_tree".substitute!("apple", "banana",
                                "tree", "shrub").equal("banana_shrub"));

// 範囲の部分範囲を置換する
assert("apple_tree".substitute!('a', 'b',
                                't', 'f').equal("bpple_free"));

// 値を置換する
writeln('a'.substitute!('a', 'b', 't', 'f')); // 'b'
Examples:
複数の代替選手
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);
static assert(is(typeof(y.front) == double));
assert(y.equal([0.2, 2, 3]));

auto z = "42".substitute('2', '3')
             .substitute('3', '1');
static assert(is(ElementType!(typeof(z)) == dchar));
assert(equal(z, "41"));
auto substitute(Value)(Value value)
if (isInputRange!Value || !is(CommonType!(Value, typeof(substs[0])) == void));
コンパイル時の置換マッピングで単一値を置換する。

複雑さ D のswitchΟ(1)を保証しているため、Ο(1)となる;

auto sum(R)(R r)
if (isInputRange!R && !isInfinite!R && is(typeof(r.front + r.front)));

auto sum(R, E)(R r, E seed)
if (isInputRange!R && !isInfinite!R && is(typeof(seed = seed + r.front)));
の要素を合計する。 rの要素を合計する。 の要素を合計する。概念的には 概念的には sum(r)と等価である。 foldと等価である。 b)(r, 0)と等価である、 sumは、精度を最大化するために特殊なアルゴリズムを使用している、 である。
  • もし std.range.primitives.ElementTypeRが浮動小数点 型であり、R が のランダムアクセス範囲である。 長さとスライスを持つランダムアクセス範囲である場合 sum対和 アルゴリズムを使用する。
  • ElementType!R が浮動小数点型で、R が有限の入力範囲(ただし、スライシングを伴うランダムアクセス範囲ではない)である場合、ペアワイズサムアルゴリズムを使用する。 有限の入力範囲(ただし、スライシングを伴うランダムアクセス範囲ではない)である場合、次のようになる。 sumKahan和アルゴリズムを使用する。
  • それ以外の場合は、単純な要素ごとの加算が行われる。
浮動小数点入力の場合、計算は real real で計算され、それ以外はdouble の精度で計算される。 (これはfold の動作から逸脱した特殊なケースである、 これは、float の範囲に対してfloat の精度を保つという の動作から逸脱した特殊なケースであることに注意されたい)。 他のすべての型では、計算は、範囲の2つの要素を加算して得られるのと同じ型で行われる。 で計算される。 型であってもよい(例えば、積分昇格の場合)。 場合)。
シードは sum.に渡すことができる。 このシードは初期値として使われるだけでなく、その型が上記をすべて上書きし、和のアルゴリズムと精度を決定する。 を決定する。シードが渡されない場合、シードは の値で作成される。 typeof(r.front + r.front)(0)または typeof(r.front + r.front).zero の値で作成される。
これらの特殊化された和算アルゴリズムは、通常の和算よりも多くのプリミティブな演算を実行することに注意されたい。 を実行することに注意されたい。したがって、精度を犠牲にしてでも最高速度が必要な場合は を使うことができる。 fold!((a, b) => a + b)(r, 0)を使うことができる。 を使うことができる。
Parameters:
E seed 和の初期値
R r 有限の入力範囲
Returns:
rの範囲にあるすべての要素の和。
Examples:
同上
import std.range;

//単純な積分和
writeln(sum([1, 2, 3, 4])); // 10

//積分促進を使う
writeln(sum([false, true, true, false, true])); // 3
writeln(sum(ubyte.max.repeat(100))); // 25500

//結果がオーバーフローする可能性がある
writeln(uint.max.repeat(3).sum()); // 4294967293U
//しかし、シードを使って和プリミティブを変更することができる
writeln(uint.max.repeat(3).sum(ulong.init)); // 12884901885UL

//浮動小数点和
writeln(sum([1.0, 2.0, 3.0, 4.0])); // 10

//浮動小数点演算には倍精度最小値がある
static assert(is(typeof(sum([1F, 2F, 3F, 4F])) == double));
writeln(sum([1F, 2, 3, 4])); // 10

//大きな整数に対してペアごとの浮動小数点和を強制する
import 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));
T mean(T = double, R)(R r)
if (isInputRange!R && isNumeric!(ElementType!R) && !isInfinite!R);

auto mean(R, T)(R r, T seed)
if (isInputRange!R && !isNumeric!(ElementType!R) && is(typeof(r.front + seed)) && is(typeof(r.front / size_t(1))) && !isInfinite!R);
範囲の平均(俗に平均と呼ばれる)を求める。
組み込みの数値型では、正確な Knuth & Welford 平均計算が使用される。 が使用される。ユーザー定義型では、要素ごとの合計が使用される。 さらに seedが必要である。 0 と等価である。
この関数の最初のオーバーロードは、範囲が空の場合、T.init を返す。 を返す。しかし、2番目のオーバーロードは seedを返す。
この関数はΟ(r.length)である。
Parameters:
T 戻り値の型。
R r 入力範囲
T seed ユーザー定義型の場合。0 と等価でなければならない。
Returns:
の平均は rが空でないとき rの平均は空でない。
Examples:
import std.math.operations : isClose;
import std.math.traits : isNaN;

static immutable arr1 = [1, 2, 3];
static immutable arr2 = [1.5, 2.5, 12.5];

assert(arr1.mean.isClose(2));
assert(arr2.mean.isClose(5.5));

assert(arr1[0 .. 0].mean.isNaN);
auto uniq(alias pred = "a == b", Range)(Range r)
if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool));
与えられた範囲の一意な連続する要素をのんびりと反復処理する。 ソートされていると仮定する。 uniqシステム ユーティリティに似た機能)。要素の等価性は、述語 predデフォルトでは"a == b" である。この述語は std.functional.binaryFunに渡され、文字列か、 を介して実行可能な任意の callable に渡され、文字列を受け取るか、pred(element, element) を介して実行できる任意の callable を受け取ることができる。与えられた範囲が 双方向である、 uniqもまた 返す。
Parameters:
pred 範囲要素間の等価性を決定する述語。
Range r 入力範囲 要素の入力範囲。
Returns:
入力範囲 連続する一意な要素の入力範囲。もし rが も前方範囲または双方向範囲である場合、返される範囲も同様になる。
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 ][]));

// コピーを使用して重複をインプレースでフィルタリングする
arr.length -= arr.uniq().copy(arr).length;
writeln(arr); // [1, 2, 3, 4, 5]

// 一意性が連続してのみ決定されることに注意; 異なる要素を
// 挟んで重複する要素は
// 削除されない:
assert(equal(uniq([ 1, 1, 2, 1, 1, 3, 1]), [1, 2, 1, 3, 1]));
Permutations!Range permutations(Range)(Range r);

struct Permutations(Range);
のすべての順列をヒープ・アルゴリズムを使ってのんびりと計算する。 rを計算する
Parameters:
Range 範囲型
Range r ランダムアクセス範囲 の順列を見つける。
Returns:
順方向範囲 である。 std.range.indexedを見る。 r.
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]]));