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

std.algorithm.mutation

これは std.algorithm. 一般的な突然変異アルゴリズムが含まれている。
カンニングペーパー
関数名 説明
bringToFront もしa = [1, 2, 3]b = [4, 5, 6, 7]bringToFront(a, b) は、a = [4, 5, 6]b = [7, 1, 2, 3].
copy 範囲を別の範囲にコピーする。もし a = [1, 2, 3]b = new int[5] の場合copy(a, b)b = [1, 2, 3, 0, 0] を残し、b[3 .. $] を返す。
fill 範囲をパターンで埋める、 例えば、もしa = new int[3], ならばfill(a, 4)a = [4, 4, 4] を残し、fill(a, [3, 4]) は残す。 a = [3, 4, 3].
initializeAll もしa = [1.2, 3.4] なら、initializeAll(a) を残す。 a = [double.init, double.init].
move move(a, b) move(a)ab に移動する。a を破壊的に読み込む。
moveEmplace move と似ているが、target が初期化されていないと仮定する。
moveAll すべての要素をある範囲から別の範囲に移動する。
moveEmplaceAll moveAll と似ているが、target のすべての要素が初期化されていないと仮定する。
moveSome 可能な限り多くの要素をある範囲から別の範囲に移動する。
moveEmplaceSome moveSome に似ているが、target のすべての要素が初期化されていないと仮定する。
remove ある範囲から要素をインプレースで削除し、短縮された範囲を返す。 を返す。
reverse a = [1, 2, 3] ,reverse(a) の場合、それを[3, 2, 1] に変更する。
strip ある "値"に等しいか、述語を満たすすべての先頭および末尾の要素を取り除く。 は述語を満たす。 もしa = [1, 1, 0, 1, 1] ならば、strip(a, 1) となる。 strip!(e => e == 1)(a)[0] を返す。
stripLeft 値に等しい、または述語を満たすすべての先頭要素を取り除く。 を満たす。 もしa = [1, 1, 0, 1, 1] ならば、stripLeft(a, 1) を返す。 stripLeft!(e => e == 1)(a)[0, 1, 1] を返す。
stripRight 値と等しいか、述語を満たすすべての末尾要素を取り除く。 を返す。 もしa = [1, 1, 0, 1, 1] ならば、stripRight(a, 1) を返す。 stripRight!(e => e == 1)(a)[1, 1, 0] を返す。
swap 二つの値を入れ替える。
swapAt インデックスによって2つの値を入れ替える。
swapRanges 2つの範囲のすべての要素を入れ替える。
uninitializedFill 範囲(未初期化と仮定)を値で埋める。
size_t bringToFront(InputRange, ForwardRange)(InputRange front, ForwardRange back)
if (isInputRange!InputRange && isForwardRange!ForwardRange);
bringToFrontは2つの範囲 frontbackを取る。 を取る。と frontbackの連結を考える、 bringToFrontを回転させる。 のすべての要素が backのすべての要素が を回転させる。の要素の相対的な順序は、次のようになる。 frontbackの要素の相対的な順序は変わらない。
関数 bringToFront関数は文字列をコード単位で扱う。 レベルで文字列を扱い、Unicode文字の整合性には関係しない。 bringToFrontは、文字列関数としてではなく、範囲の要素を移動する関数として設計されている。 を移動させる関数として設計されており、文字列関数としては設計されていない。
swapΟ(max(front.length, back.length)) 評価を行う。
この bringToFront関数は1つのバッファの要素を左右に回転させたり、同じ長さのバッファを入れ替えたりすることができる。 バッファの要素を左右に入れ替えることができる。 バッファ間で要素を移動させることもできる。

前提条件 以下のいずれかである。 frontbackが不一致であるか backが から到達可能である。 frontfrontback からは到達できない。

Parameters:
InputRange front 入力レンジ
ForwardRange back 前方範囲
Returns:
前方に持ってくる要素の数、つまり back.
See Also:
Examples:
の最も単純な使い方は bringToFrontの最も簡単な使用法は バッファのエレメントを回転させることである。例:":
auto arr = [4, 5, 6, 7, 1, 2, 3];
auto p = bringToFront(arr[0 .. 4], arr[4 .. $]);
writeln(p); // arr.length - 4
writeln(arr); // [1, 2, 3, 4, 5, 6, 7]
Examples:
を超えることがある。 frontを「踏み越える」可能性がある。 back を "踏み越える"ことができる。これは、上記の のような、快適に右境界の部分範囲を計算できない前方範囲では非常に便利である。 これは、上記のarr[0 .. 4] のような、快適に右境界の部分範囲を計算することができない前進範囲では非常に便利である。以下の例では 以下の例では、r2r1 の右部分範囲である。
import std.algorithm.comparison : equal;
import std.container : SList;
import std.range.primitives : popFrontN;

auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3);
auto r1 = list[];
auto r2 = list[]; popFrontN(r2, 4);
assert(equal(r2, [ 1, 2, 3 ]));
bringToFront(r1, r2);
assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ]));
Examples:
異なるタイプのレンジ間で要素を入れ替えることができる:
import std.algorithm.comparison : equal;
import std.container : SList;

auto list = SList!(int)(4, 5, 6, 7);
auto vec = [ 1, 2, 3 ];
bringToFront(list[], vec);
assert(equal(list[], [ 1, 2, 3, 4 ]));
assert(equal(vec, [ 5, 6, 7 ]));
Examples:
ユニコードの整合性は保たれない:
import std.string : representation;
auto ar = representation("a".dup);
auto br = representation("ç".dup);

bringToFront(ar, br);

auto a = cast(char[]) ar;
auto b = cast(char[]) br;

// 不正なUTF-8
writeln(a); // "\303"
// 不正なUTF-8
writeln(b); // "\247a"
TargetRange copy(SourceRange, TargetRange)(SourceRange source, TargetRange target)
if (isInputRange!SourceRange && isOutputRange!(TargetRange, ElementType!SourceRange));
の内容を sourceの内容を targetにコピーし の残りの(埋まっていない)部分を返す。 target.

前提条件 targetを収容するのに十分なスペースがなければならない。 の全体を収容するのに十分なスペースがなければならない。 source.

Parameters:
SourceRange source 入力範囲
TargetRange target 出力範囲
Returns:
ターゲットの未記入部分
Examples:
int[] a = [ 1, 5 ];
int[] b = [ 9, 8 ];
int[] buf = new int[](a.length + b.length + 10);
auto rem = a.copy(buf);    // aをbufにコピーする
rem = b.copy(rem);         // bをbufの残りにコピーする
writeln(buf[0 .. a.length + b.length]); // [1, 5, 9, 8]
assert(rem.length == 10);   // bufの未使用スロット
Examples:
ターゲット・レンジ・エレメントがソース・レンジ・エレメントからの割り当てをサポートする限り、異なるタイプのレンジが受け入れられる。 ターゲット範囲要素がソース範囲要素からの割り当てをサポートする限り、異なるタイプの範囲が受け入れられる:
float[] src = [ 1.0f, 5 ];
double[] dest = new double[src.length];
src.copy(dest);
Examples:
範囲から最大でn の要素をコピーするには、次のようにする。 std.range.take:
import std.range;
int[] src = [ 1, 5, 8, 9, 10 ];
auto dest = new int[](3);
src.take(dest.length).copy(dest);
writeln(dest); // [1, 5, 8]
Examples:
述語を満たす範囲の要素だけをコピーする、 を使う。 filter:
import std.algorithm.iteration : filter;
int[] src = [ 1, 5, 8, 9, 10, 1, 2, 0 ];
auto dest = new int[src.length];
auto rem = src
    .filter!(a => (a & 1) == 1)
    .copy(dest);
writeln(dest[0 .. $ - rem.length]); // [1, 5, 9, 1]
Examples:
std.range.retroに似た動作を実現するために使用できる。 STLのcopy_backward':
import std.algorithm, std.range;
int[] src = [1, 2, 4];
int[] dest = [0, 0, 0, 0, 0];
src.retro.copy(dest.retro);
writeln(dest); // [0, 0, 1, 2, 4]
void fill(Range, Value)(auto ref Range range, auto ref Value value)
if (isInputRange!Range && is(typeof(range.front = value)) || isSomeChar!Value && is(typeof(range[] = value)));

void fill(InputRange, ForwardRange)(InputRange range, ForwardRange filler)
if (isInputRange!InputRange && (isForwardRange!ForwardRange || isInputRange!ForwardRange && isInfinite!ForwardRange) && is(typeof(InputRange.init.front = ForwardRange.init.front)));
入力範囲の各要素に valueを入力範囲の各要素に割り当てる。 range.
あるいは valueを埋めるために range, a filler前方範囲 を指定することもできる。の長さは fillerrangeの長さは一致する必要はないが fillerは空であってはならない。
Parameters:
Range range 入力範囲 入力範囲 要素への参照を公開し、割り当て可能な 要素を持つ。
Value value 範囲の各要素に割り当てられる
ForwardRange filler A 前方範囲 塗りつぶしパターンを表す。
Throws:
もし fillerが空の場合
Examples:
int[] a = [ 1, 2, 3, 4 ];
fill(a, 5);
writeln(a); // [5, 5, 5, 5]
Examples:
int[] a = [ 1, 2, 3, 4, 5 ];
int[] b = [ 8, 9 ];
fill(a, b);
writeln(a); // [8, 9, 8, 9, 8]
void initializeAll(Range)(Range range)
if (isInputRange!Range && hasLvalueElements!Range && hasAssignableElements!Range && __traits(compiles, () { static ElementType!Range _; } ));

void initializeAll(Range)(Range range)
if (is(Range == char[]) || is(Range == wchar[]));
のすべての要素を初期化する。 rangeのすべての要素を.init の値で初期化する。 範囲の要素は初期化されていないと仮定する。
この関数は、Tstruct で、T.this() が でアノテーションされている場合は使用できない。 が@disable である場合、この関数は利用できない。
Parameters:
Range range 入力範囲 入力範囲 要素への参照を公開し、割り当て可能な 要素を持つ。
Examples:
import core.stdc.stdlib : malloc, free;

struct S
{
    int a = 10;
}

auto s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5];
initializeAll(s);
writeln(s); // [S(10), S(10), S(10), S(10), S(10)]

scope(exit) free(s.ptr);
void move(T)(ref T source, ref T target);

T move(T)(ref return scope T source);
移動する sourceに移動する。 targetに移動する。
T がデストラクタまたはポストブリットが定義された構造体である場合、ソースはターゲットに移動された後、 の値にリセットされる。 .init の値はリセットされる。 は変更されない。

前提条件 ソースが自身を指す内部ポインタを持ち、かつ を定義していない場合、移動できず、アサーション失敗のトリガーとなる。

Parameters:
T source コピーするデータ
T target どこにコピーするか。デストラクタがあれば、コピーが実行される前に呼び出される。 が呼び出される。
Examples:
非構造体型では moveを実行するだけである。 target = source:
Object obj1 = new Object;
Object obj2 = obj1;
Object obj3;

move(obj2, obj3);
assert(obj3 is obj1);
// obj2 変更なし
assert(obj2 is obj1);
Examples:
// デストラクタのない構造体は、単にコピーされる
struct S1
{
    int a = 1;
    int b = 2;
}
S1 s11 = { 10, 11 };
S1 s12;

move(s11, s12);

writeln(s12); // S1(10, 11)
writeln(s11); // s12

// しかし、デストラクタやポストブリットを持つ構造体は、ターゲットにコピーされた後、
// その.init値にリセットされる。
struct S2
{
    int a = 1;
    int b = 2;

    ~this() pure nothrow @safe @nogc { }
}
S2 s21 = { 3, 4 };
S2 s22;

move(s21, s22);

writeln(s21); // S2(1, 2)
writeln(s22); // S2(3, 4)
Examples:
コピー不可能な構造体も移動できる:
struct S
{
    int a = 1;
    @disable this(this);
    ~this() pure nothrow @safe @nogc {}
}
S s1;
s1.a = 2;
S s2 = move(s1);
writeln(s1.a); // 1
writeln(s2.a); // 2
Examples:
opPostMove が定義されていれば呼び出される:
struct S
{
    int a;
    void opPostMove(const ref S old)
    {
        writeln(a); // old.a
        a++;
    }
}
S s1;
s1.a = 41;
S s2 = move(s1);
writeln(s2.a); // 42
pure @system void moveEmplace(T)(ref T source, ref T target);
と似ている。 moveに似ているが targetは初期化されていない。これは の方が効率的である。 sourceこの方が効率的である。 target これはより効率的である。
Parameters:
T source ターゲットに移される値
T target ソースが埋める未初期化の値
Examples:
static struct Foo
{
pure nothrow @nogc:
    this(int* ptr) { _ptr = ptr; }
    ~this() { if (_ptr) ++*_ptr; }
    int* _ptr;
}

int val;
Foo foo1 = void; // 未初期化
auto foo2 = Foo(&val); // 初期化
assert(foo2._ptr is &val);

// `move(foo2, foo1)`を使用すると、 初期化されていないfoo1が破壊されるため、
// 予期せぬ結果となる。
// moveEmplaceは、foo1を破壊または初期化することなく、直接上書きする。
moveEmplace(foo2, foo1);
assert(foo1._ptr is &val);
assert(foo2._ptr is null);
writeln(val); // 0
InputRange2 moveAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(move(src.front, tgt.front))));
の各要素a に対してmove(a, b) を呼び出す。 srcと対応する の各要素b tgtを呼び出す。

前提条件 walkLength(src) <= walkLength(tgt). この前提条件がアサートされる。もし tgtに十分なスペースが確保できない場合は srcを使用する。 moveSomeを代わりに使う。

Parameters:
InputRange1 src 可動要素を持つ入力範囲。 可動要素を持つ入力範囲。
InputRange2 tgt を持つ入力範囲。 要素を持つ入力範囲。 srcに移動できる要素を持つ入力範囲。
Returns:
の残りの部分である。 tgtのすべての要素が srcの残りの部分である。 の残りの部分である。
Examples:
int[3] a = [ 1, 2, 3 ];
int[5] b;
assert(moveAll(a[], b[]) is b[3 .. $]);
writeln(a[]); // b[0 .. 3]
int[3] cmp = [ 1, 2, 3 ];
writeln(a[]); // cmp[]
@system InputRange2 moveEmplaceAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(moveEmplace(src.front, tgt.front))));
に似ている。 moveAllに似ているが tgtの要素はすべて未初期化である。 が未初期化であると仮定する。要素を moveEmplaceから要素を移動するには srcの要素を tgt.
Examples:
static struct Foo
{
    ~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
    int* _ptr;
}
int[3] refs = [0, 1, 2];
Foo[3] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2])];
Foo[5] dst = void;

auto tail = moveEmplaceAll(src[], dst[]); // 3つの値をsrcからdstに移動する
assert(tail.length == 2); // 初期化されていない残りの値を返す
initializeAll(tail);

import std.algorithm.searching : all;
assert(src[].all!(e => e._ptr is null));
assert(dst[0 .. 3].all!(e => e._ptr !is null));
Tuple!(InputRange1, InputRange2) moveSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(move(src.front, tgt.front))));
の各要素a に対してmove(a, b) を呼び出す。 srcと対応する の各要素b tgtの各要素について、対応する要素ごとに。 を呼び出す。
Parameters:
InputRange1 src 可動要素を持つ 可動要素を持つ入力範囲。
InputRange2 tgt を持つ入力範囲。 要素を持つ入力範囲。 srcに移動できる要素を持つ入力範囲。
Returns:
2つの範囲のどちらか一方を使い果たした後の、残った部分。 2つの範囲のどちらか一方を使い果たした後の残りの部分。
Examples:
int[5] a = [ 1, 2, 3, 4, 5 ];
int[3] b;
assert(moveSome(a[], b[])[0] is a[3 .. $]);
writeln(a[0 .. 3]); // b
writeln(a); // [1, 2, 3, 4, 5]
@system Tuple!(InputRange1, InputRange2) moveEmplaceSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(move(src.front, tgt.front))));
と同じである。 moveSomeと同じであるが tgtの要素はすべて未初期化である。 が未初期化であると仮定する。要素を moveEmplaceから要素を移動するには srcの要素を tgt.
Examples:
static struct Foo
{
    ~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
    int* _ptr;
}
int[4] refs = [0, 1, 2, 3];
Foo[4] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2]), Foo(&refs[3])];
Foo[3] dst = void;

auto res = moveEmplaceSome(src[], dst[]);
writeln(res.length); // 2

import std.algorithm.searching : all;
assert(src[0 .. 3].all!(e => e._ptr is null));
assert(src[3]._ptr !is null);
assert(dst[].all!(e => e._ptr !is null));
enum SwapStrategy: int;
範囲の要素を入れ替える必要があるアルゴリズム(分割やソートなど)のためのスワッピング戦略を定義する。 スワップ戦略を定義する。戦略 は、アルゴリズムの中心的な関心事ではない要素のスワップに関するものである。 要素のスワップに関するものである。例えば、toUpper(a) < toUpper(b) に従って[ "abc", "b", "aBc" ] をソートするアルゴリズムを考える。 という2つの等価な文字列を入れ替える。"abc""aBc" 。と はどちらも有効なので、ソートには影響しない。 ["abc", "aBc", "b" ][ "aBc", "abc", "b" ] の両方が有効だからである。 はどちらも有効なので、ソートには影響しない。
状況によっては、アルゴリズムが等価な要素の相対的な順序を決して変更してはならない。 等価な要素の相対的な順序を変更してはならない状況もある(上の例では [ "abc", "aBc", "b" ] が正しい結果となる)。そのような アルゴリズムは,stable と呼ばれる。順序付けアルゴリズムが,任意に 等価な要素を任意に入れ替えることができる場合,その順序付けはunstable と呼ばれる。
さらにもう1つのアルゴリズム・クラスは、次のような中間的なトレードオフを選択する。 によって,中間的なトレードオフを選択することができる。このような 本ライブラリではこれをsemistable と呼ぶ。
一般的に、stable 順序付け戦略は、他の2つよりも時間的・空間的にコストがかかる場合がある。 がかかるため、他の2つよりも時間的・空間的にコストがかかる場合がある。 制約が追加されるためである。同様に、semistable は、unstable よりもコストが高くなる可能性がある。 によってパラメータ化される。 SwapStrategyすべての を選ぶ。 SwapStrategy.unstableをデフォルトとする。
Examples:
int[] a = [0, 1, 2, 3];
writeln(remove!(SwapStrategy.stable)(a, 1)); // [0, 2, 3]
a = [0, 1, 2, 3];
writeln(remove!(SwapStrategy.unstable)(a, 1)); // [0, 3, 2]
Examples:
import std.algorithm.sorting : partition;

// 3より大きいものを左に置く
auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
writeln(partition!(a => a > 3, SwapStrategy.stable)(arr)); // [1, 2, 3]
writeln(arr); // [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
writeln(partition!(a => a > 3, SwapStrategy.semistable)(arr)); // [2, 3, 1]
writeln(arr); // [4, 5, 6, 7, 8, 9, 10, 2, 3, 1]

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
writeln(partition!(a => a > 3, SwapStrategy.unstable)(arr)); // [3, 2, 1]
writeln(arr); // [10, 9, 8, 4, 5, 6, 7, 3, 2, 1]
unstable
出力がアルゴリズムの要求を満たす限り、要素を自由に入れ替えることができる。 アルゴリズムの要求を満たす限り、要素を自由に入れ替えることができる。
semistable
範囲を2つに分割するアルゴリズムでは、分割点の左側でのみ要素の相対順序を保持する。 分割点の左側にのみ要素の相対順序を保持する。
stable
要素の相対順序を、アルゴリズムの要件で許される最大限の範囲で保持する。 アルゴリズムの要求で許される最大範囲まで要素の相対順序を保持する。
Range remove(SwapStrategy s = SwapStrategy.stable, Range, Offset...)(Range range, Offset offset)
if (Offset.length >= 1 && allSatisfy!(isValidIntegralTuple, Offset));

Range remove(SwapStrategy s = SwapStrategy.stable, Range, Offset...)(Range range, Offset offset)
if (Offset.length >= 1 && !allSatisfy!(isValidIntegralTuple, Offset));
から与えられたオフセットにある要素を削除し、短縮された要素を返す。 rangeから与えられたオフセットにある要素を削除し、短縮された 範囲を返す。
例えば、配列から1つの要素を削除する方法を以下に示す:
import std.algorithm.mutation;
string[] a = [ "a", "b", "c", "d" ];
a = a.remove(1); // オフセット1の要素を削除する
assert(a == [ "a", "c", "d"]);
注釈:」である。 removeは元の範囲の長さを直接変更しない; 代わりに、短くなった範囲を返す。その返り値が元の範囲に代入されなければ、元の範囲は元の長さを保つ。 に代入されない場合、元の範囲は元の長さを保つ。 その内容は変更される:
import std.algorithm.mutation;
int[] a = [ 3, 5, 7, 8 ];
assert(remove(a, 1) == [ 3, 7, 8 ]);
assert(a == [ 3, 7, 8, 8 ]);
オフセット1 の要素が削除され、残りの要素がその場所を埋めるようにシフトアップされた。 しかし、元の配列は同じ長さのままである。 のままである。これは、std.algorithm のすべての関数が、トポロジーではなく 内容のみを変更するためである。8 "値"は繰り返される。 moveが繰り返されているからだ。 が要素を並べ替えるために呼び出されたからである。また、整数の場合、move は単にコピー元をコピー先にコピーするだけである。 をコピーするだけである。 a 、削除の効果で置き換えるには、単純に によって返されたスライスを removeで返されたスライスを代入するだけである。

複数の要素を削除する

複数のインデックスを remove.その場合 に渡すことができる。インデックスは でなければならない。
import std.algorithm.mutation;
int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
assert(remove(a, 1, 3, 5) ==
    [ 0, 2, 4, 6, 7, 8, 9, 10 ]);
すべてのインデックスは、元の配列のスロットを指している。 のスロットを指す。
インデックスの範囲を削除するには、2つの整数オフセットのタプルを与えることができる:
import std.algorithm.mutation, std.typecons;
int[] a = [ 3, 4, 5, 6, 7];
// インデックス1と2の要素を削除する
assert(remove(a, tuple(1, 3)) == [ 3, 6, 7 ]);
このタプルは、左側が閉じていて右側が開いている範囲を通過する。 を渡す(組み込みのスライスと一致する)。tuple(1, 3) はインデックス12 を意味するが、3 を意味しない。
最後に、積分オフセットと2つの積分オフセットで構成されるタプルの 組み合わせを渡すことができる。 で構成されるタプルを渡すことができる:
import std.algorithm.mutation, std.typecons;
int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
a = remove(a, 1, tuple(3, 5), 9);
assert(a == [ 0, 2, 5, 6, 7, 8, 10 ]);
この場合、ポジション1、3、4、9のスロットはアレイから取り除かれる。 から取り除かれる。

移動戦略

範囲内のいくつかの要素を削除する必要があるが、残りの要素の順序は保持する必要がない場合 の順序を保持する必要がない場合は、次のようにする。 にSwapStrategy.unstableremove.
import std.algorithm.mutation;
int[] a = [ 0, 1, 2, 3 ];
assert(remove!(SwapStrategy.unstable)(a, 1) == [ 0, 3, 2 ]);
上記の場合、スロット1 の要素は削除されるが、範囲の最後の要素に置き換えられる。 の要素は削除され、範囲の最後の要素に置き換えられる。安定性要求の緩和を利用して を利用する、 removeの端から要素を移動させた。 を削除されるスロットの上に移動させる。こうすることで、データ の移動が少なくなり、関数の実行時間が改善される。
removeは、代入可能な l値 "要素を持つ双方向範囲に作用する。移動戦略は次の通りである(速いものから遅いものへとリストされている):
  • もしs == SwapStrategy.unstable && isRandomAccessRange!Range && hasLength!Range && hasLvalueElements!Range ならば、要素は範囲の末尾から充填されるスロットに移動される。 の場合、要素は範囲の端から、埋められるべきスロットに移動される。この場合 移動の絶対最小値が実行される。
  • そうでない場合、もしs == SwapStrategy.unstable && isBidirectionalRange!Range && hasLength!Range && hasLvalueElements!Range なら、要素はやはり範囲の端から移動される。 を繰り返し呼び出すことで、スロット間の移動に時間が費やされる。 への呼び出しが繰り返される。 range.popFront.
  • そうでなければ、要素は の前方へ段階的に移動される。 rangeある要素が何度も移動されることはない。 ある要素が何度も移動されることはないが、前の場合よりも多くの要素が移動される。 より多くの要素が移動される。
Parameters:
s 元の注文を維持する必要があるかどうかを判断するためのSwapStrategy
Range range 双方向の範囲 長さメンバを持つ
Offset offset どの要素を削除するか
Returns:
の要素を含む範囲。 rangeの要素を含む範囲で、1つ以上の要素を削除する。
Examples:
import std.typecons : tuple;

auto a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy.stable)(a, 1)); // [0, 2, 3, 4, 5]
a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy.stable)(a, 1, 3)); // [0, 2, 4, 5]
a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy.stable)(a, 1, tuple(3, 6))); // [0, 2]

a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy.unstable)(a, 1)); // [0, 5, 2, 3, 4]
a = [ 0, 1, 2, 3, 4, 5 ];
writeln(remove!(SwapStrategy.unstable)(a, tuple(1, 4))); // [0, 5, 4]
Examples:
import std.typecons : tuple;

// インデックスを削除する
writeln([4, 5, 6].remove(1)); // [4, 6]

// 複数のインデックスを削除する
writeln([4, 5, 6, 7, 8].remove(1, 3)); // [4, 6, 8]

// インデックスの範囲を使用する
writeln([4, 5, 6, 7, 8].remove(tuple(1, 3))); // [4, 7, 8]

// インデックスの範囲と個々のインデックスを使用する
writeln([4, 5, 6, 7, 8].remove(0, tuple(1, 3), 4)); // [7]
Examples:
SwapStrategy.unstable の方が速いが、元の配列と同じ順序は保証されない。
writeln([5, 6, 7, 8].remove!(SwapStrategy.stable)(1)); // [5, 7, 8]
writeln([5, 6, 7, 8].remove!(SwapStrategy.unstable)(1)); // [5, 8, 7]
Range remove(alias pred, SwapStrategy s = SwapStrategy.stable, Range)(Range range);
の長さを短くする。 双方向rangeを満たす predを満たす要素を取り除くことで、双方向範囲の長さを短くする。もしs = SwapStrategy.unstable 、 の要素が範囲の右端から移動される。 に移動する。もしs = SwapStrategy.stable (デフォルト)なら 要素は、相対的な順序が保たれるように、徐々に前に移動される。 の順序が保たれる。フィルタリングされた範囲を返す。
Parameters:
Range range l値要素を持つ双方向範囲 または変更可能な文字配列。
Returns:
predtrue 削除される
Examples:
static immutable base = [1, 2, 3, 2, 4, 2, 5, 2];

int[] arr = base[].dup;

// 文字列ベースの述語を使う
writeln(remove!("a == 2")(arr)); // [1, 3, 4, 5]

// 元の配列の内容が変更されているので、
// 元の状態に戻す必要がある。
// ただし、長さは変更されていない。
arr[] = base[];

// ラムダ述語を使う
writeln(remove!(a => a == 2)(arr)); // [1, 3, 4, 5]
Range reverse(Range)(Range r)
if (isBidirectionalRange!Range && (hasSwappableElements!Range || hasAssignableElements!Range && hasLength!Range && isRandomAccessRange!Range || isNarrowString!Range && isAssignable!(ElementType!Range)));
反転する rを行う。 を行う。 r.length / 2swapの評価を行う。 複数のコード単位からなる UTF シーケンスは適切に保存される。
Parameters:
Range r 双方向範囲 スワップ可能な要素を持つ双方向範囲、長さメンバを持つランダムアクセス範囲、 または狭い文字列
Returns:
r

注釈 文字にunicode修飾子(\u0301 、 この関数は修飾子の位置を正しく保持しない。例:("bád")を反転すると、duuuとなる、 ba\u0301d ("bád")を逆にすると、("dáb")の代わりにdu0301ab ("d́ab")となる。 da\u0301b ("dáb")となる。

See Also:
std.range.retroを変更することなく、ダラダラとリバースする。 r
Examples:
int[] arr = [ 1, 2, 3 ];
writeln(arr.reverse); // [3, 2, 1]
Examples:
char[] arr = "hello\U00010143\u0100\U00010143".dup;
writeln(arr.reverse); // "\U00010143\u0100\U00010143olleh"
Range strip(Range, E)(Range range, E element)
if (isBidirectionalRange!Range && is(typeof(range.front == element) : bool));

Range strip(alias pred, Range)(Range range)
if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool));

Range stripLeft(Range, E)(Range range, E element)
if (isInputRange!Range && is(typeof(range.front == element) : bool));

Range stripLeft(alias pred, Range)(Range range)
if (isInputRange!Range && is(typeof(pred(range.front)) : bool));

Range stripRight(Range, E)(Range range, E element)
if (isBidirectionalRange!Range && is(typeof(range.back == element) : bool));

Range stripRight(alias pred, Range)(Range range)
if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool));
strip関数群は、先頭、末尾、または先頭と末尾の両方の要素を取り除くことができる、 または先頭と末尾の両方の要素を取り除くことができる。
関数 stripLeft関数はfront 、 関数 stripRight関数はback 、 一方 strip関数はfrontback の両方を取り除く。
である。 stripstripRight関数は、範囲が である必要がある。 BidirectionalRangeの範囲でなければならない。
これらの関数はすべて2種類ある:1つはターゲット要素を取る、 一方はターゲット要素を取り、この要素が見つかる限り、範囲が取り除かれる。 もう1つはラムダ述語を受け取り、述語が真を返す限り範囲が取り除かれる。 述語がtrueを返す限り、範囲は取り除かれる。
Parameters:
Range range 双方向レンジ または入力範囲
E element 削除する要素
Returns:
要素を除いた範囲を開始と終了に持つ範囲
Examples:
先頭と末尾の要素を対象要素と等しく取り除く。
writeln("  foobar  ".strip(' ')); // "foobar"
writeln("00223.444500".strip('0')); // "223.4445"
writeln("ëëêéüŗōpéêëë".strip('ë')); // "êéüŗōpéê"
writeln([1, 1, 0, 1, 1].strip(1)); // [0]
writeln([0.0, 0.01, 0.01, 0.0].strip(0).length); // 2
Examples:
述語がtrueを返す間、先頭と末尾の要素を取り除く。
writeln("  foobar  ".strip!(a => a == ' ')()); // "foobar"
writeln("00223.444500".strip!(a => a == '0')()); // "223.4445"
writeln("ëëêéüŗōpéêëë".strip!(a => a == 'ë')()); // "êéüŗōpéê"
writeln([1, 1, 0, 1, 1].strip!(a => a == 1)()); // [0]
writeln([0.0, 0.01, 0.5, 0.6, 0.01, 0.0].strip!(a => a < 0.4)().length); // 2
Examples:
ターゲット要素に等しい先行要素を取り除く。
writeln("  foobar  ".stripLeft(' ')); // "foobar  "
writeln("00223.444500".stripLeft('0')); // "223.444500"
writeln("ůůűniçodêéé".stripLeft('ů')); // "űniçodêéé"
writeln([1, 1, 0, 1, 1].stripLeft(1)); // [0, 1, 1]
writeln([0.0, 0.01, 0.01, 0.0].stripLeft(0).length); // 3
Examples:
述語がtrueを返す間、先頭の要素を取り除く。
writeln("  foobar  ".stripLeft!(a => a == ' ')()); // "foobar  "
writeln("00223.444500".stripLeft!(a => a == '0')()); // "223.444500"
writeln("ůůűniçodêéé".stripLeft!(a => a == 'ů')()); // "űniçodêéé"
writeln([1, 1, 0, 1, 1].stripLeft!(a => a == 1)()); // [0, 1, 1]
writeln([0.0, 0.01, 0.10, 0.5, 0.6].stripLeft!(a => a < 0.4)().length); // 2
Examples:
ターゲット要素に等しい末尾の要素を取り除く。
writeln("  foobar  ".stripRight(' ')); // "  foobar"
writeln("00223.444500".stripRight('0')); // "00223.4445"
writeln("ùniçodêéé".stripRight('é')); // "ùniçodê"
writeln([1, 1, 0, 1, 1].stripRight(1)); // [1, 1, 0]
writeln([0.0, 0.01, 0.01, 0.0].stripRight(0).length); // 3
Examples:
述語が真を返す間、末尾の要素を取り除く。
writeln("  foobar  ".stripRight!(a => a == ' ')()); // "  foobar"
writeln("00223.444500".stripRight!(a => a == '0')()); // "00223.4445"
writeln("ùniçodêéé".stripRight!(a => a == 'é')()); // "ùniçodê"
writeln([1, 1, 0, 1, 1].stripRight!(a => a == 1)()); // [1, 1, 0]
writeln([0.0, 0.01, 0.10, 0.5, 0.6].stripRight!(a => a > 0.4)().length); // 3
pure nothrow @nogc @trusted void swap(T)(ref T lhs, ref T rhs)
if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))));

void swap(T)(ref T lhs, ref T rhs)
if (is(typeof(lhs.proxySwap(rhs))));
スワップ lhsそして rhs.インスタンス lhsrhsインスタンスと は、opAssign や他の関数を呼び出すことなく、メモリ上に移動される。T は、スワップされるために割り当て可能である必要はまったくない。
もし lhsrhsが同じインスタンスを参照する場合、何も行われない。
lhsそして rhsは変更可能でなければならない。もしT が構造体または共用体であれば、そのフィールドもすべて(再帰的に)ミュータブルでなければならない。 そのフィールドもすべて(再帰的に)変更可能でなければならない。
Parameters:
T lhs スワップするデータ rhs.
T rhs スワップされるデータ lhs.
Examples:
// POD(プレーン・オールド・データ)型を入れ替える:
int a = 42, b = 34;
swap(a, b);
assert(a == 34 && b == 42);

// インダイレクトで構造体を交換する:
static struct S { int x; char c; int[] y; }
S s1 = { 0, 'z', [ 1, 2 ] };
S s2 = { 42, 'a', [ 4, 6 ] };
swap(s1, s2);
writeln(s1.x); // 42
writeln(s1.c); // 'a'
writeln(s1.y); // [4, 6]

writeln(s2.x); // 0
writeln(s2.c); // 'z'
writeln(s2.y); // [1, 2]

// イミュータブルはスワップできない:
immutable int imm1 = 1, imm2 = 2;
static assert(!__traits(compiles, swap(imm1, imm2)));

int c = imm1 + 0;
int d = imm2 + 0;
swap(c, d);
writeln(c); // 2
writeln(d); // 1
Examples:
// コピー不可能な型でもスワップは可能である。
static struct NoCopy
{
    this(this) { assert(0); }
    int n;
    string s;
}
NoCopy nc1, nc2;
nc1.n = 127; nc1.s = "abc";
nc2.n = 513; nc2.s = "uvwxyz";

swap(nc1, nc2);
assert(nc1.n == 513 && nc1.s == "uvwxyz");
assert(nc2.n == 127 && nc2.s == "abc");

swap(nc1, nc1);
swap(nc2, nc2);
assert(nc1.n == 513 && nc1.s == "uvwxyz");
assert(nc2.n == 127 && nc2.s == "abc");

// コピー不可能なフィールドを含む型もスワップできる。
static struct NoCopyHolder
{
    NoCopy noCopy;
}
NoCopyHolder h1, h2;
h1.noCopy.n = 31; h1.noCopy.s = "abc";
h2.noCopy.n = 65; h2.noCopy.s = null;

swap(h1, h2);
assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");

swap(h1, h1);
swap(h2, h2);
assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");

// const型はスワップできない。
const NoCopy const1, const2;
assert(const1.n == 0 && const2.n == 0);
static assert(!__traits(compiles, swap(const1, const2)));
void swapAt(R)(auto ref R r, size_t i1, size_t i2);
2つの要素を入れ替える。 r, で指定される i1i2.
Parameters:
R r 入れ替え可能な要素を持つ範囲
size_t i1 最初のインデックス
size_t i2 第二インデックス
Examples:
import std.algorithm.comparison : equal;
auto a = [1, 2, 3];
a.swapAt(1, 2);
assert(a.equal([1, 3, 2]));
Tuple!(InputRange1, InputRange2) swapRanges(InputRange1, InputRange2)(InputRange1 r1, InputRange2 r2)
if (hasSwappableElements!InputRange1 && hasSwappableElements!InputRange2 && is(ElementType!InputRange1 == ElementType!InputRange2));
のすべての要素を入れ替える。 r1の連続する要素と入れ替える。 r2. の残りの部分を含むタプルを返す。 r1r2 のスワップされなかった残りの部分を含むタプルを返す(そのうちの1つは空になる)。範囲は は異なる型であってもよいが、同じ要素型を持ち、スワッピングをサポートしなければならない。 をサポートしていなければならない。
Parameters:
InputRange1 r1 入力範囲 スワップ可能な要素を持つ
InputRange2 r2 入力範囲 スワップ可能な要素を持つ
Returns:
r1とr2のスワップされなかった余り部分を含むタプル
Examples:
import std.range : empty;
int[] a = [ 100, 101, 102, 103 ];
int[] b = [ 0, 1, 2, 3 ];
auto c = swapRanges(a[1 .. 3], b[2 .. 4]);
assert(c[0].empty && c[1].empty);
writeln(a); // [100, 2, 3, 103]
writeln(b); // [0, 1, 101, 102]
void uninitializedFill(Range, Value)(Range range, Value value)
if (isInputRange!Range && hasLvalueElements!Range && is(typeof(range.front = value)));
の各要素を初期化する。 rangeで初期化する。 value. 範囲の要素は初期化されていないと仮定する。 これは、コピーコンストラクタを定義する構造体にとって興味深いことである。 コピー・コンストラクタを定義している構造体にとって興味深い、 fillと uninitializedFillは等価である)。
Parameters:
Range range また 入力範囲 要素への参照を公開し、割り当て可能な 要素を持つ。
Value value 範囲の各要素に割り当てられる
Examples:
import core.stdc.stdlib : malloc, free;

auto s = (cast(int*) malloc(5 * int.sizeof))[0 .. 5];
uninitializedFill(s, 42);
writeln(s); // [42, 42, 42, 42, 42]

scope(exit) free(s.ptr);