英語版
このページの英語版を見る
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) はa をb に移動する。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 | 範囲(未初期化と仮定)を値で埋める。 |
License:
Authors:
- size_t
bringToFront
(InputRange, ForwardRange)(InputRangefront
, ForwardRangeback
)
if (isInputRange!InputRange && isForwardRange!ForwardRange); bringToFront
は2つの範囲front
とback
を取る。 を取る。とfront
とback
の連結を考える、bringToFront
を回転させる。 のすべての要素がback
のすべての要素が を回転させる。の要素の相対的な順序は、次のようになる。front
とback
の要素の相対的な順序は変わらない。関数bringToFront
関数は文字列をコード単位で扱う。 レベルで文字列を扱い、Unicode文字の整合性には関係しない。bringToFront
は、文字列関数としてではなく、範囲の要素を移動する関数として設計されている。 を移動させる関数として設計されており、文字列関数としては設計されていない。 swap のΟ(max(front.length, back.length)) 評価を行う。 このbringToFront
関数は1つのバッファの要素を左右に回転させたり、同じ長さのバッファを入れ替えたりすることができる。 バッファの要素を左右に入れ替えることができる。 バッファ間で要素を移動させることもできる。前提条件 以下のいずれかである。
front
とback
が不一致であるかback
が から到達可能である。front
とfront
は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] のような、快適に右境界の部分範囲を計算することができない前進範囲では非常に便利である。以下の例では 以下の例では、r2 はr1 の右部分範囲である。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)(SourceRangesource
, TargetRangetarget
)
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 Rangerange
, auto ref Valuevalue
)
if (isInputRange!Range && is(typeof(range
.front =value
)) || isSomeChar!Value && is(typeof(range
[] =value
)));
voidfill
(InputRange, ForwardRange)(InputRangerange
, ForwardRangefiller
)
if (isInputRange!InputRange && (isForwardRange!ForwardRange || isInputRange!ForwardRange && isInfinite!ForwardRange) && is(typeof(InputRange.init.front = ForwardRange.init.front))); - 入力範囲の各要素に
value
を入力範囲の各要素に割り当てる。range
.あるいはvalue
を埋めるためにrange
, afiller
前方範囲 を指定することもできる。の長さはfiller
とrange
の長さは一致する必要はないがfiller
は空であってはならない。Parameters:Throws:もしfiller
が空の場合See Also: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)(Rangerange
)
if (isInputRange!Range && hasLvalueElements!Range && hasAssignableElements!Range && __traits(compiles, () { static ElementType!Range _; } ));
voidinitializeAll
(Range)(Rangerange
)
if (is(Range == char[]) || is(Range == wchar[])); - のすべての要素を初期化する。
range
のすべての要素を.init の値で初期化する。 範囲の要素は初期化されていないと仮定する。この関数は、T がstruct で、T.this() が でアノテーションされている場合は使用できない。 が@disable である場合、この関数は利用できない。Parameters:Range range
入力範囲 入力範囲 要素への参照を公開し、割り当て可能な 要素を持つ。 See Also: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 Tsource
, ref Ttarget
);
Tmove
(T)(ref return scope Tsource
); - 移動する
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 Tsource
, ref Ttarget
); - 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)(InputRange1src
, InputRange2tgt
)
if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(move(src
.front,tgt
.front)))); - の各要素a に対してmove(a, b) を呼び出す。
src
と対応する の各要素btgt
を呼び出す。前提条件 walkLength(
src
) <= walkLength(tgt
). この前提条件がアサートされる。もしtgt
に十分なスペースが確保できない場合はsrc
を使用する。 moveSomeを代わりに使う。Parameters: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)(InputRange1src
, InputRange2tgt
)
if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(moveEmplace(src
.front,tgt
.front)))); - 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)(InputRange1src
, InputRange2tgt
)
if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(move(src
.front,tgt
.front)))); - の各要素a に対してmove(a, b) を呼び出す。
src
と対応する の各要素btgt
の各要素について、対応する要素ごとに。 を呼び出す。Parameters: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)(InputRange1src
, InputRange2tgt
)
if (isInputRange!InputRange1 && isInputRange!InputRange2 && is(typeof(move(src
.front,tgt
.front)))); - 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...)(Rangerange
, Offsetoffset
)
if (Offset.length >= 1 && allSatisfy!(isValidIntegralTuple, Offset));
Rangeremove
(SwapStrategy s = SwapStrategy.stable, Range, Offset...)(Rangerange
, Offsetoffset
)
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 ]);
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 ]);
import std.algorithm.mutation, std.typecons; int[] a = [ 3, 4, 5, 6, 7]; // インデックス1と2の要素を削除する assert(remove(a, tuple(1, 3)) == [ 3, 6, 7 ]);
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 ]);
移動戦略
範囲内のいくつかの要素を削除する必要があるが、残りの要素の順序は保持する必要がない場合 の順序を保持する必要がない場合は、次のようにする。 にSwapStrategy.unstable 。remove
.import std.algorithm.mutation; int[] a = [ 0, 1, 2, 3 ]; assert(remove!(SwapStrategy.unstable)(a, 1) == [ 0, 3, 2 ]);
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)(Rangerange
); - の長さを短くする。 双方向
range
を満たす predを満たす要素を取り除くことで、双方向範囲の長さを短くする。もしs = SwapStrategy.unstable 、 の要素が範囲の右端から移動される。 に移動する。もしs = SwapStrategy.stable (デフォルト)なら 要素は、相対的な順序が保たれるように、徐々に前に移動される。 の順序が保たれる。フィルタリングされた範囲を返す。Parameters:Range range
l値要素を持つ双方向範囲 または変更可能な文字配列。 Returns:pred 。true 削除される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)(Ranger
)
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)(Rangerange
, Eelement
)
if (isBidirectionalRange!Range && is(typeof(range
.front ==element
) : bool));
Rangestrip
(alias pred, Range)(Rangerange
)
if (isBidirectionalRange!Range && is(typeof(pred(range
.back)) : bool));
RangestripLeft
(Range, E)(Rangerange
, Eelement
)
if (isInputRange!Range && is(typeof(range
.front ==element
) : bool));
RangestripLeft
(alias pred, Range)(Rangerange
)
if (isInputRange!Range && is(typeof(pred(range
.front)) : bool));
RangestripRight
(Range, E)(Rangerange
, Eelement
)
if (isBidirectionalRange!Range && is(typeof(range
.back ==element
) : bool));
RangestripRight
(alias pred, Range)(Rangerange
)
if (isBidirectionalRange!Range && is(typeof(pred(range
.back)) : bool)); - strip関数群は、先頭、末尾、または先頭と末尾の両方の要素を取り除くことができる、 または先頭と末尾の両方の要素を取り除くことができる。関数
stripLeft
関数はfront 、 関数stripRight
関数はback 、 一方strip
関数はfront とback の両方を取り除く。 である。strip
とstripRight
関数は、範囲が である必要がある。 BidirectionalRangeの範囲でなければならない。 これらの関数はすべて2種類ある:1つはターゲット要素を取る、 一方はターゲット要素を取り、この要素が見つかる限り、範囲が取り除かれる。 もう1つはラムダ述語を受け取り、述語が真を返す限り範囲が取り除かれる。 述語がtrueを返す限り、範囲は取り除かれる。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 Tlhs
, ref Trhs
)
if (isBlitAssignable!T && !is(typeof(lhs
.proxySwap(rhs
))));
voidswap
(T)(ref Tlhs
, ref Trhs
)
if (is(typeof(lhs
.proxySwap(rhs
)))); - スワップ
lhs
そしてrhs
.インスタンスlhs
とrhs
インスタンスと は、opAssign や他の関数を呼び出すことなく、メモリ上に移動される。T は、スワップされるために割り当て可能である必要はまったくない。もしlhs
とrhs
が同じインスタンスを参照する場合、何も行われない。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 Rr
, size_ti1
, size_ti2
); - 2つの要素を入れ替える。
r
, で指定されるi1
とi2
.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)(InputRange1r1
, InputRange2r2
)
if (hasSwappableElements!InputRange1 && hasSwappableElements!InputRange2 && is(ElementType!InputRange1 == ElementType!InputRange2)); - のすべての要素を入れ替える。
r1
の連続する要素と入れ替える。r2
. の残りの部分を含むタプルを返す。r1
とr2 のスワップされなかった残りの部分を含むタプルを返す(そのうちの1つは空になる)。範囲は は異なる型であってもよいが、同じ要素型を持ち、スワッピングをサポートしなければならない。 をサポートしていなければならない。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)(Rangerange
, Valuevalue
)
if (isInputRange!Range && hasLvalueElements!Range && is(typeof(range
.front =value
))); - の各要素を初期化する。
range
で初期化する。value
. 範囲の要素は初期化されていないと仮定する。 これは、コピーコンストラクタを定義する構造体にとって興味深いことである。 コピー・コンストラクタを定義している構造体にとって興味深い、 fillと uninitializedFillは等価である)。Parameters:Range range
また 入力範囲 要素への参照を公開し、割り当て可能な 要素を持つ。 Value value
範囲の各要素に割り当てられる See Also: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);
Copyright © 1999-2024 by the D Language Foundation
DEEPL APIにより翻訳、ところどころ修正。
このページの最新版(英語)
このページの原文(英語)
翻訳時のdmdのバージョン: 2.108.0
ドキュメントのdmdのバージョン: 2.109.1
翻訳日付 :
HTML生成日時:
編集者: dokutoku