std.range
ガイド 範囲の理解を深めるための記事は数多く公開されている。
- Ali Çehreli による、 範囲の基礎と、範囲ベースのコードの作成に関するチュートリアル。
- ジョナサン・M・デイビスによる「Ranges入門 」DConf 2015での講演。中核的な構成から実用的なアドバイスまで、生き生きとした紹介。
- DLang Tour の範囲に関する章では、 インタラクティブな入門編を紹介している。
- H. S. Teoh による コンポーネントプログラミングのチュートリアルでは、 複雑なアルゴリズムに対する範囲ベースのプログラミングの影響について、実世界でのショーケースを紹介している。
- アンドレイ・アレクサンドレスクの論文 「反復について」では、範囲の概念的な側面と動機について
部分モジュール このモジュールには2つの部分モジュールがある。
std.range.primitivesサブモジュールは、 基本的な範囲の機能を提供する。これは、与えられたオブジェクトが範囲であるかどうか、どのような種類の範囲であるか、 そしていくつかの一般的な範囲操作を 提供する。std.range.interfacesサブモジュールは、 実行時多相性により、オブジェクトベースのインターフェイスで範囲を操作する。 このモジュールの残りの部分では、範囲の作成と合成のための豊富なテンプレートを提供し、 既存の範囲から新しい範囲を構築できるようにする。chain | 複数の範囲を1つの範囲に連結する。 |
choose | 実行時に、ブール値の条件に基づいて2つの範囲のいずれかを選択する。 |
chooseAmong | インデックスに基づいて、実行時に複数の範囲から1つを選択する。 |
chunks | 元のレンジから固定サイズのチャンクを返すレンジを作成する 。 |
cycle | 与えられた順方向の範囲を無限に繰り返す無限の範囲を作成する。 循環バッファの実装に便利。 |
drop | 指定した範囲から最初の n 個の要素を削除した結果となる範囲を作成する 。 |
dropBack | 与えられた範囲から最後の n 個の要素を破棄した結果の 範囲を作成する。 |
dropExactly | 与えられた範囲の最初の要素から正確にn 個を削除した結果の 範囲を作成する。 |
dropBackExactly | 指定した範囲の最後の要素から正確にn 個の要素を削除した結果となる範囲を作成する。 |
dropOne | 指定した範囲の最初の要素を削除した結果の 範囲を作成する。 |
dropBackOne | 指定した範囲から最後の要素を削除した結果の 範囲を作成する。 |
enumerate | 添え字変数付きの範囲を反復する。 |
evenChunks | 元の範囲からほぼ同じ長さのチャンクをいくつか返す範囲を作成する 。 |
frontTransversal | 与えられた範囲の最初の要素を順に処理する範囲を作成する 。 |
generate | 指定した関数を順次呼び出すことで、範囲を作成する。これにより、 単一のデリゲートとして範囲を作成することができる。 |
indexed | あたかも、与えられた範囲の要素が 与えられたインデックスの範囲に従って並べ替えられたかのように、与えられた範囲のビューを提供する範囲を作成する。 |
iota | 開始点と終了点の間の数値で構成される範囲を 作成し、指定された間隔で間を空ける。 |
lockstep | foreachループで使用するために、n 個の範囲を順番に繰り返す。zip と同様だが、lockstep はforeach ループ専用に設計されている。 |
nullSink | 受信したデータを破棄する出力範囲。 |
only | 指定された引数を繰り返し処理する範囲を作成する。 |
padLeft | 指定した要素を範囲の先頭に追加することで、範囲を指定した長さに揃える 。範囲の長さが既知の場合は、遅延処理される。 |
padRight | 与えられた要素を範囲の後ろに追加することで、範囲を指定の長さに遅延パディングする。 |
radial | ランダムアクセス可能な範囲と開始点が与えられた場合、 開始点から見て次の左の要素と次の右の要素を交互に返す範囲を作成する 。 |
recurrence | 数学的帰納法によって定義された値を持つ順方向の範囲を作成する 。 |
refRange | 参照渡しで範囲を渡す。元の範囲と RefRange は 常にまったく同じ要素を持つ。 どちらか一方に対して実行された操作は、もう一方にも影響する。 |
repeat | 単一の要素をn 回繰り返す範囲、またはその要素を無限に繰り返す無限の範囲を作成する 。 |
retro | 双方向の範囲を後ろ向きに反復する。 |
roundRobin | n個の範囲が与えられた場合、新しい範囲を作成し、 各範囲の最初のn個の要素を順番に返し、次に各範囲の2番目の要素を返し、 以下同様に、ラウンドロビン方式で返す。 |
sequence | recurrence と同様だが、ランダムアクセス可能な範囲が作成される点が異なる。 |
slide | 元の範囲に対して固定サイズのスライディングウィンドウを返す範囲を作成する。 チャンクとは異なり、 一度に設定可能な数のアイテムを順次進めるもので、 一度にチャンクを1つずつ進めるものではない。 |
stride | 範囲をステップn で繰り返す。 |
tail | 与えられた範囲の末尾からn 個以内の範囲を返す 。 |
take | 与えられた範囲の最初の n 個までの要素のみで構成されるサブ範囲を作成する 。 |
takeExactly | take と同様だが、与えられた範囲には実際にn個の要素が存在すると仮定する 。したがって、length プロパティも定義される。 |
takeNone | 指定された範囲の最初の要素から最後の要素までをランダムアクセス可能な範囲として作成する。 |
takeOne | 指定された範囲の最初の要素のみで構成されるランダムアクセス範囲を作成する 。 |
tee | 与えられた範囲をラップする範囲を作成し、 その要素に沿って進むとともに、各要素で指定された関数を呼び出す。 |
transposed | 範囲の並び替えを行う。 |
transversal | 与えられたランダムアクセス範囲のn 番目の要素を順に繰り返す範囲を作成する 。 |
zip | n個の範囲が与えられた場合、順次、 最初の要素のタプル、2番目の要素のタプル、 など を返す範囲を作成する。 |
ソート 要素がソートされた範囲は、特定の操作においてより高い効率性を実現する。 このために、 assumeSorted関数を使用して、 事前にソートされた範囲から SortedRange事前にソートされた範囲から構築する。 std.algorithm.sorting.sort関数は、 を返すこともできる SortedRange。 SortedRangeオブジェクトは、 範囲がソートされていることを利用した追加の
- auto
retro
(Range)(Ranger
)
if (isBidirectionalRange!(Unqual!Range)); - 双方向の範囲を後ろ向きに反復する。元の範囲は、source プロパティを使用してアクセスできる。同じ範囲にretroを2回適用すると、 元の範囲が得られる。Parameters:
Range r
双方向の範囲を逆方向に反復する Returns: 双方向範囲の長さ双方向範囲の長さもr
長さも提供する。または、r
ランダムアクセス範囲である場合、戻り値もランダムアクセスとなる。See Also:length直接std.algorithm.mutation.reverseソース範囲を直接変更する。Examples:import std.algorithm.comparison : equal; int[5] a = [ 1, 2, 3, 4, 5 ]; int[5] b = [ 5, 4, 3, 2, 1 ]; assert(equal(retro(a[]), b[])); assert(retro(a[]).source is a[]); assert(retro(retro(a[])) is a[]);
- auto
stride
(Range)(Ranger
, size_tn
)
if (isInputRange!(Unqual!Range)); - 範囲を反復する
r
ストライドでn
。 範囲がランダムアクセス可能な範囲である場合は、 その範囲にインデックスを指定して移動する。 そうでない場合は、popFront を連続して呼び出すことで移動する。 同じ範囲に対してストライドを2回適用すると、 ステップが 2回の適用結果となる。 0であることはエラーであるn
0になることはあり得ません。Parameters:Range r
入力範囲を飛び越える size_t n
スキップする要素数 Returns: 最小値として、入力範囲。結果として得られる範囲は、 基礎となる範囲のレンジプリミティブを採用する。xml-ph-0000@deepl.internalxml-ph-0000@deepl.internal少なくとも、入力範囲。結果として得られる範囲は、 xml-ph-0000@deepl.internal である限り、 std.range.primitives.hasLengthtrue である限り、Examples:import std.algorithm.comparison : equal; int[] a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]; assert(equal(stride(a, 3), [ 1, 4, 7, 10 ][])); writeln(stride(stride(a, 2), 3)); // stride(a, 6)
- auto
chain
(Ranges...)(Rangesrs
)
if (Ranges.length > 0 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void)); - 複数の範囲を順番にまたがる。この関数は、
chain
任意の 数の範囲を受け取り、Chain!(R1, R2,...) オブジェクトを返す。 範囲は異なっていてもよいが、同じ要素型でなければならない。 結果は、front 、popFront 、empty のプリミティブを提供する範囲となる。すべての入力範囲がランダムアクセスとlength を提供する場合、Chain もそれらを提供する。結果として得られる範囲のランダムアクセスを繰り返すと、パフォーマンスが低下する可能性が高いことに注意 すること。これは、チェーン内の範囲の長さを ランダムアクセス操作ごとに合計する必要があるためである。最初の残りの範囲の要素へのランダムアクセスは 依然として効率的である。 Chain または に1つの範囲のみが提供される場合、chain
、Chain 型は、その範囲の型に直接エイリアス化することで、その場から消える。Parameters:Ranges rs
入力範囲を連結する Returns: 最小値の入力範囲。すべての範囲が最小値の場合、最小値の入力範囲。 すべての範囲がrs
範囲プリミティブを提供している場合、返される範囲にもその範囲プリミティブが提供される 。 range primitive範囲プリミティブSee Also:only値を範囲に連結するExamples:import std.algorithm.comparison : equal; int[] arr1 = [ 1, 2, 3, 4 ]; int[] arr2 = [ 5, 6 ]; int[] arr3 = [ 7 ]; auto s = chain(arr1, arr2, arr3); writeln(s.length); // 7 writeln(s[5]); // 6 assert(equal(s, [1, 2, 3, 4, 5, 6, 7][]));
Examples: 範囲のプリミティブは、すべての範囲がそれらを提供している場合、範囲のプリミティブは、 すべての範囲がそれらを提供している場合、import std.algorithm.comparison : equal; import std.algorithm.sorting : sort; int[] arr1 = [5, 2, 8]; int[] arr2 = [3, 7, 9]; int[] arr3 = [1, 4, 6]; // すべての配列を対象としたインプレースソート auto s = arr1.chain(arr2, arr3).sort; assert(s.equal([1, 2, 3, 4, 5, 6, 7, 8, 9])); assert(arr1.equal([1, 2, 3])); assert(arr2.equal([4, 5, 6])); assert(arr3.equal([7, 8, 9]));
Examples: D言語の安全な型変換により、異なる文字範囲を連結すると、xml-ph-0000@deepl.internalという範囲が生成される。xml-ph-0001@deepl.internalD言語の安全な型昇格により、異なる文字範囲を連結すると、uint という文字範囲が生成される。 必要な型を取得するには、byChar 、byWchar、 byDcharを範囲に対して使用する。import std.utf : byChar, byCodeUnit; auto s1 = "string one"; auto s2 = "string two"; // s1とs2の先頭は、自動デコードのためのdcharである static assert(is(typeof(s1.front) == dchar) && is(typeof(s2.front) == dchar)); auto r1 = s1.chain(s2); // 同じ文字型の範囲のチェーンは、同じ型を与える static assert(is(typeof(r1.front) == dchar)); auto s3 = "string three".byCodeUnit; static assert(is(typeof(s3.front) == immutable char)); auto r2 = s1.chain(s3); // 文字型の混合範囲を連結すると、`dchar`になる static assert(is(typeof(r2.front) == dchar)); // 文字の範囲に対してbyCharを使用して、正しくUTF-8に変換する auto r3 = s1.byChar.chain(s3); static assert(is(typeof(r3.front) == immutable char));
- auto
choose
(R1, R2)(boolcondition
, return scope R1r1
, return scope R2r2
)
if (isInputRange!(Unqual!R1) && isInputRange!(Unqual!R2) && !is(CommonType!(ElementType!(Unqual!R1), ElementType!(Unqual!R2)) == void)); - 実行時に、ブール値の条件に応じて2つの範囲のいずれかを選択する。範囲は異なる可能性があるが、互換性のある要素型でなければならない(すなわち、 2つの要素型に対してCommonType が存在しなければならない)。結果として得られる範囲は、 2つのうちで最も機能が弱いものである(例えば、R1 がランダムアクセス可能な範囲であり、R2 が前方範囲である場合、ForwardRange となる)。Parameters:
bool condition
どの範囲を選択するか: r1
true の場合は、r2
そうでなければ、R1 r1
「真」の範囲 R2 r2
「偽」の範囲 Returns: xml-ph-0000@deepl.internalとxml-ph-0001@deepl.internalに依存する範囲の種類。xml-ph-0000@deepl.internalxml-ph-0000@deepl.internalR1 とR2 に依存する範囲の型。Examples:import std.algorithm.comparison : equal; import std.algorithm.iteration : filter, map; auto data1 = only(1, 2, 3, 4).filter!(a => a != 3); auto data2 = only(5, 6, 7, 8).map!(a => a + 1); // choose()は主に、実行時に異なる型の2つの範囲から // 1つを選択する必要がある場合に役立つ。 static assert(!is(typeof(data1) == typeof(data2))); auto chooseRange(bool pickFirst) { // 返される範囲は、型エラーが発生することなく、 // どちらの範囲も返したり保存したりするために使用できる共通のラッパータイプである。 return choose(pickFirst, data1, data2); // 単に、choose()を使用せずに選択した範囲を返しても動作しない。なぜなら、 // types.map()とfilter()は異なる型を返すからだ。 //return pickFirst ? data1 : data2; // コンパイルされない } auto result = chooseRange(true); assert(result.equal(only(1, 2, 4))); result = chooseRange(false); assert(result.equal(only(6, 7, 8, 9)));
- auto
chooseAmong
(Ranges...)(size_tindex
, return scope Rangesrs
)
if (Ranges.length >= 2 && allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) && !is(CommonType!(staticMap!(ElementType, Ranges)) == void)); - 実行時に複数の範囲から1つを選択する。範囲は異なっていてもよいが、互換性のある要素型でなければならない。 結果として得られるのは、Ranges の最も弱い機能を提供する範囲である。Parameters: どの範囲を選択するかは、範囲の数よりも少ない数でなければならない。
size_t index
どの範囲を選択するかは、範囲の数より少ない数でなければならない Ranges rs
2つ以上の範囲 Returns: インデックス付きの範囲。rs が1つの範囲のみで構成されている場合、戻り値の型はその範囲の型のエイリアスとなる。rangerangeインデックス付きの範囲。rs が1つの範囲のみで構成されている場合、戻り値の型は その範囲の型のエイリアスとなる。Examples:auto test() { import std.algorithm.comparison : equal; int[4] sarr1 = [1, 2, 3, 4]; int[2] sarr2 = [5, 6]; int[1] sarr3 = [7]; auto arr1 = sarr1[]; auto arr2 = sarr2[]; auto arr3 = sarr3[]; { auto s = chooseAmong(0, arr1, arr2, arr3); auto t = s.save; writeln(s.length); // 4 writeln(s[2]); // 3 s.popFront(); assert(equal(t, only(1, 2, 3, 4))); } { auto s = chooseAmong(1, arr1, arr2, arr3); writeln(s.length); // 2 s.front = 8; assert(equal(s, only(8, 6))); } { auto s = chooseAmong(1, arr1, arr2, arr3); writeln(s.length); // 2 s[1] = 9; assert(equal(s, only(8, 9))); } { auto s = chooseAmong(1, arr2, arr1, arr3)[1 .. 3]; writeln(s.length); // 2 assert(equal(s, only(2, 3))); } { auto s = chooseAmong(0, arr1, arr2, arr3); writeln(s.length); // 4 writeln(s.back); // 4 s.popBack(); s.back = 5; assert(equal(s, only(1, 2, 5))); s.back = 3; assert(equal(s, only(1, 2, 3))); } { uint[5] foo = [1, 2, 3, 4, 5]; uint[5] bar = [6, 7, 8, 9, 10]; auto c = chooseAmong(1, foo[], bar[]); writeln(c[3]); // 9 c[3] = 42; writeln(c[3]); // 42 writeln(c.moveFront()); // 6 writeln(c.moveBack()); // 10 writeln(c.moveAt(4)); // 10 } { import std.range : cycle; auto s = chooseAmong(0, cycle(arr2), cycle(arr3)); assert(isInfinite!(typeof(s))); assert(!s.empty); writeln(s[100]); // 8 writeln(s[101]); // 9 assert(s[0 .. 3].equal(only(8, 9, 8))); } return 0; } // 実行時に動作する auto a = test(); // そしてコンパイル時も static b = test();
- auto
roundRobin
(Rs...)(Rsrs
)
if (Rs.length > 1 && allSatisfy!(isInputRange, staticMap!(Unqual, Rs))); - roundRobin(r1, r2, r3) r1.front 、次に 、 次に となり、その後、それぞれから要素を1つ取り除き、 再び から繰り返す。例えば、2つの範囲が関与している場合、 2つの範囲から交互に要素が生成される。r2.front r3.front r1to stop停止
roundRobin
すべての範囲を消費し終えると停止する(早く終わったものはスキップする )。Examples:import std.algorithm.comparison : equal; int[] a = [ 1, 2, 3 ]; int[] b = [ 10, 20, 30, 40 ]; auto r = roundRobin(a, b); assert(equal(r, [ 1, 10, 2, 20, 3, 30, 40 ]));
Examples:roundRobin を使用すると、 範囲内の各要素の間に要素を挿入する「インターリーブ」機能を作成できる。import std.algorithm.comparison : equal; auto interleave(R, E)(R range, E element) if ((isInputRange!R && hasLength!R) || isForwardRange!R) { static if (hasLength!R) immutable len = range.length; else immutable len = range.save.walkLength; return roundRobin( range, element.repeat(len - 1) ); } assert(interleave([1, 2, 3], 0).equal([1, 0, 2, 0, 3]));
roundRobinroundRobin - auto
radial
(Range, I)(Ranger
, IstartingIndex
)
if (isRandomAccessRange!(Unqual!Range) && hasLength!(Unqual!Range) && hasSlicing!(Unqual!Range) && isIntegral!I);
autoradial
(R)(Rr
)
if (isRandomAccessRange!(Unqual!R) && hasLength!(Unqual!R) && hasSlicing!(Unqual!R)); - 指定したポイントから開始し、 そのポイントから左右に段階的に拡張するランダムアクセス範囲を反復する。初期ポイントが指定されていない場合、 反復は範囲の中央から開始する。反復は範囲全体にわたって行われる。
startingIndex
0 の場合、範囲は順番に完全に反復処理される。 また、r
.length指定されている場合は、Parameters:Range r
長さを持つランダムアクセス可能な範囲と、 I startingIndex
インデックスをスライスして反復を開始する Returns: 前方の順方向の範囲length長さ前方の順方向の範囲の長さExamples:import std.algorithm.comparison : equal; int[] a = [ 1, 2, 3, 4, 5 ]; assert(equal(radial(a), [ 3, 4, 2, 5, 1 ])); a = [ 1, 2, 3, 4 ]; assert(equal(radial(a), [ 2, 3, 1, 4 ])); // 最初に左端が到達した場合、右側の残りの要素は // 順番に連結される: a = [ 0, 1, 2, 3, 4, 5 ]; assert(equal(radial(a, 1), [ 1, 2, 0, 3, 4, 5 ])); // 右端に最初に到達した場合、左側の残りの要素は // 逆順で連結される: assert(equal(radial(a, 4), [ 4, 5, 3, 2, 1, 0 ]));
- Take!R
take
(R)(Rinput
, size_tn
)
if (isInputRange!(Unqual!R));
structTake
(Range) if (isInputRange!(Unqual!Range) && !(!isInfinite!(Unqual!Range) && hasSlicing!(Unqual!Range) || is(Range T ==Take
!T)));
templateTake
(R) if (isInputRange!(Unqual!R) && (!isInfinite!(Unqual!R) && hasSlicing!(Unqual!R) || is(R T ==Take
!T))) - 遅延処理により、最大
n
範囲の要素だけを取得します。これは 特に無限の範囲を使用する場合に便利です。takeExactly、take
要素が存在する必要はありません。n
要素以上が存在する必要はありません。input
。そのため、 length 情報が結果に適用されるのは、input
長さ情報も 持っていない限り、Parameters:R input
入力範囲を 反復処理して、最大 n
要素数size_t n
要素の数だけ繰り返す Returns: 少なくとも、入力範囲。その範囲がランダムアクセス可能であり、xml-ph-0000@deepl.internalxml-ph-0000@deepl.internalxml-ph-0000@deepl.internal少なくとも、入力範囲。その範囲がランダムアクセスを提供し、length が 提供する場合は、take
それらも提供する。Examples:import std.algorithm.comparison : equal; int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; auto s = take(arr1, 5); writeln(s.length); // 5 writeln(s[4]); // 5 assert(equal(s, [ 1, 2, 3, 4, 5 ][]));
Examples:範囲が要素の前に終了する場合は、n
要素がなくなる前に、take
単にその範囲全体を返します ( takeExactly、範囲が早期に終了した場合にアサーションエラーが発生するのとは異なり、import std.algorithm.comparison : equal; int[] arr2 = [ 1, 2, 3 ]; auto t = take(arr2, 5); writeln(t.length); // 3 assert(equal(t, [ 1, 2, 3 ]));
assertion failureアサーションエラー - auto
takeExactly
(R)(Rrange
, size_tn
)
if (isInputRange!R); - と同様だが、 takeが、
range
少なくともn 個の要素を持つと想定します。したがって、takeExactly(range, n)の結果は 常にlength プロパティを定義し(そして、それを初期化しますn
range
length を定義していない場合でも、結果はinternalinternaltakeExactly
、元の範囲が xml-ph-0000@deepl.internal を定義している場合、または無限である場合の take元の範囲がlength を定義している場合、または無限である場合 とは異なり、 take、しかし、要素数が1未満のレンジを渡すことは違法であるn
takeExactly
。これはアサーションエラーの原因となる。Examples:最大1つの要素を持つ範囲を返します。例えば、xml-ph-0000@deepl.internal は整数xml-ph-0001@deepl.internal からなる範囲を返します。xml-phを呼び出すimport std.algorithm.comparison : equal; auto a = [ 1, 2, 3, 4, 5 ]; auto b = takeExactly(a, 3); assert(equal(b, [1, 2, 3])); static assert(is(typeof(b.length) == size_t)); writeln(b.length); // 3 writeln(b.front); // 1 writeln(b.back); // 3
- auto
takeOne
(R)(Rsource
)
if (isInputRange!R); - 最大でも1つの要素を持つ範囲を返します。例えば、takeOne([42, 43, 44]) は整数42 からなる範囲を返します。popFront() をその範囲から呼び出すと、その範囲は空になります。事実上、range範囲
takeOne
(r)take(r, 1) とほぼ同義ですが、 特定のインターフェイスでは、その範囲が最大でも1つの要素しか持たないことを静的に知っておくことが重要です。 によって返される型はtakeOne
ランダムアクセス可能な長さを持つ範囲である。R の機能に関係なく、順方向の範囲であれば、 ( とのもう一つの違いであるtakeOne
take。 (D R) が入力範囲であっても順方向の範囲でない場合、戻り値の型は 保存以外のすべてのランダムアクセス機能を持つ入力範囲となる。Examples:range範囲auto s = takeOne([42, 43, 44]); static assert(isRandomAccessRange!(typeof(s))); writeln(s.length); // 1 assert(!s.empty); writeln(s.front); // 42 s.front = 43; writeln(s.front); // 43 writeln(s.back); // 43 writeln(s[0]); // 43 s.popFront(); writeln(s.length); // 0 assert(s.empty);
- auto
takeNone
(R)()
if (isInputRange!R); - 静的に空であることが分かっており、length であることが保証され、R の機能に関係なくランダムアクセスが可能である 空の範囲を返す。xml-ph-0001@deepl.internalxml-ph-0001@deepl.internalExamples:
auto range = takeNone!(int[])(); writeln(range.length); // 0 assert(range.empty);
- auto
takeNone
(R)(Rrange
)
if (isInputRange!R); - Ο (1) で指定された範囲から空の範囲を作成する。可能であれば、 同じ範囲型を返す。不可能であれば、takeExactly(range, 0) を返す。emailemailExamples:
import std.algorithm.iteration : filter; assert(takeNone([42, 27, 19]).empty); assert(takeNone("dlang.org").empty); assert(takeNone(filter!"true"([42, 27, 19])).empty);
- auto
tail
(Range)(Rangerange
, size_tn
)
if (isInputRange!Range && !isInfinite!Range && (hasLength!Range || isForwardRange!Range)); - 末尾から_n 要素以内の範囲を先頭に戻す
range
。Unixのtailユーティリティに相当する範囲として意図されている。 長さがOmicronOmicronrange
が_n 以下である場合、range
そのまま返される。 スライスをサポートし、長さを持つ範囲については、Ο(1)ステップで完了する。 それ以外のすべての範囲については、Ο(range.length)時間で完了する。Parameters:Range range
範囲の末尾を取得する size_t n
テールに含める要素の最大数 Returns: テールを返す。tailtail末尾を返す。range
長さ情報を付加したExamples:convenience function便利機能// tail -c n writeln([1, 2, 3].tail(1)); // [3] writeln([1, 2, 3].tail(2)); // [2, 3] writeln([1, 2, 3].tail(3)); // [1, 2, 3] writeln([1, 2, 3].tail(4)); // [1, 2, 3] writeln([1, 2, 3].tail(0).length); // 0 // tail --lines=n import std.algorithm.comparison : equal; import std.algorithm.iteration : joiner; import std.exception : assumeWontThrow; import std.string : lineSplitter; assert("one\ntwo\nthree" .lineSplitter .tail(2) .joiner("\n") .equal("two\nthree") .assumeWontThrow);
- R
drop
(R)(Rrange
, size_tn
)
if (isInputRange!R);
RdropBack
(R)(Rrange
, size_tn
)
if (isBidirectionalRange!R); - 呼び出しと返却を行う便利な関数 std.range.primitives.popFrontN(注
range
,n
)range
。drop
これにより、要素を範囲から取り出して、 それを単一の式内で別の関数に渡すことが容易になる。popFrontN では複数の文が必要になるが、注釈
drop
、dropBack
要素のみにポップアップ表示されますがn
要素のみにポップアップ表示され、最初に範囲が空の場合は停止する。 他の言語では、これはskip と呼ばれることもある。Parameters:R range
ドロップする入力範囲 size_t n
削除する要素の数 Returns:range
最大でn
要素が削除されるExamples:element要素import std.algorithm.comparison : equal; writeln([0, 2, 1, 5, 0, 3].drop(3)); // [5, 0, 3] writeln("hello world".drop(6)); // "world" assert("hello world".drop(50).empty); assert("hello world".take(6).drop(3).equal("lo "));
Examples:import std.algorithm.comparison : equal; writeln([0, 2, 1, 5, 0, 3].dropBack(3)); // [0, 2, 1] writeln("hello world".dropBack(6)); // "hello" assert("hello world".dropBack(50).empty); assert("hello world".drop(4).dropBack(4).equal("o w"));
- R
dropExactly
(R)(Rrange
, size_tn
)
if (isInputRange!R);
RdropBackExactly
(R)(Rrange
, size_tn
)
if (isBidirectionalRange!R); 注釈 drop とは異なり、
dropExactly
範囲には少なくとも 要素が含まれていると仮定するn
。これにより、dropExactly
drop よりも高速になりますが、range
少なくとも 1つの要素が含まれていないn
要素が含まれていない場合、空の範囲に対してpopFrontを呼び出そうと試みる ことになり、これは未定義の動作となります。そのため、popFrontExactly は、range
少なくともn
。Parameters:R range
入力範囲から削除する size_t n
削除する要素の数 Returns:withだrange
要素が削除されたn
要素が削除されたExamples:、 convenience function便利機能import std.algorithm.comparison : equal; import std.algorithm.iteration : filterBidirectional; auto a = [1, 2, 3]; writeln(a.dropExactly(2)); // [3] writeln(a.dropBackExactly(2)); // [1] string s = "日本語"; writeln(s.dropExactly(2)); // "語" writeln(s.dropBackExactly(2)); // "日" auto bd = filterBidirectional!"true"([1, 2, 3]); assert(bd.dropExactly(2).equal([3])); assert(bd.dropBackExactly(2).equal([1]));
- R
dropOne
(R)(Rrange
)
if (isInputRange!R);
RdropBackOne
(R)(Rrange
)
if (isBidirectionalRange!R); - 呼び出しと返却を行う便利関数
range
.popFront()戻り値を返すrange
。dropOne
これにより、要素を範囲から取り出して、 それを単一の式内で別の関数に渡すことが容易になる。 一方、popFront では複数の文が必要になる。to provide提供するdropBackOne
同じ機能を提供するが、代わりにrange
.popBack()。Examples:range範囲import std.algorithm.comparison : equal; import std.algorithm.iteration : filterBidirectional; import std.container.dlist : DList; auto dl = DList!int(9, 1, 2, 3, 9); assert(dl[].dropOne().dropBackOne().equal([1, 2, 3])); auto a = [1, 2, 3]; writeln(a.dropOne()); // [2, 3] writeln(a.dropBackOne()); // [1, 2] string s = "日本語"; import std.exception : assumeWontThrow; assert(assumeWontThrow(s.dropOne() == "本語")); assert(assumeWontThrow(s.dropBackOne() == "日本")); auto bd = filterBidirectional!"true"([1, 2, 3]); assert(bd.dropOne().equal([2, 3])); assert(bd.dropBackOne().equal([1, 2]));
- struct
Repeat
(T);
Repeat!Trepeat
(T)(Tvalue
);
Take!(Repeat!T)repeat
(T)(Tvalue
, size_tn
); - 1つの値を繰り返す範囲を作成する。Parameters: 繰り返す値を
T value
繰り返す値 size_t n
繰り返す回数 value
Returns:n
定義されていない場合、スライスによる無限のランダムアクセス範囲。n
定義されている場合は、スライス機能付きのランダムアクセス範囲。Examples:random access rangeランダムアクセス範囲import std.algorithm.comparison : equal; assert(5.repeat().take(4).equal([5, 5, 5, 5]));
Examples:import std.algorithm.comparison : equal; assert(5.repeat(4).equal([5, 5, 5, 5]));
- inout @property inout(T)
front
();
inout @property inout(T)back
();
enum boolempty
;
voidpopFront
();
voidpopBack
();
inout @property autosave
();
inout inout(T)opIndex
(size_t);
autoopSlice
(size_ti
, size_tj
);
enum autoopDollar
;
inout autoopSlice
(size_t, DollarToken); - 範囲のプリミティブ
- auto
generate
(Fun)(Funfun
)
if (isCallable!fun
);
autogenerate
(alias fun)()
if (isCallable!fun); - 与えられたコール可能 (std.traits.isCallable)
fun
、範囲として作成する。 その先頭は、連続した呼び出しによって定義されるfun
()。 これは、グローバルな副作用を持つ関数(ランダム関数)を呼び出す場合や、front/popFront/empty の構造全体ではなく、単一のデリゲートとして表現される範囲を作成する場合に特に役立つ。fun
テンプレートエイリアスパラメータ(既存の 関数、デリゲート、static opCall を定義する構造体型)または 実行時値引数(デリゲート、関数オブジェクト)を渡すことができる。 結果の範囲は InputRange をモデル化する (std.range.primitives.isInputRange。 結果の範囲は、fun
()生成時に呼び出され、popFront へのすべての呼び出しに対して、front が呼び出された場合はキャッシュされた値が返される。Returns:inputRange では、各要素が fun への別の呼び出しを表している。Examples:funfunimport std.algorithm.comparison : equal; import std.algorithm.iteration : map; int i = 1; auto powersOfTwo = generate!(() => i *= 2)().take(10); assert(equal(powersOfTwo, iota(1, 11).map!"2^^a"()));
Examples:funfunimport std.algorithm.comparison : equal; //実行時デリゲートを返す auto infiniteIota(T)(T low, T high) { T i = high; return (){if (i == high) i = low; return i++;}; } //範囲として適応された。 assert(equal(generate(infiniteIota(1, 4)).take(10), [1, 2, 3, 1, 2, 3, 1, 2, 3, 1]));
Examples:与えられた前方の範囲を無限に繰り返す。元の範囲が 無限である場合(その場合、import std.format : format; import std.random : uniform; auto r = generate!(() => uniform(0, 6)).take(10); format("%(%s %)", r);
- struct
Cycle
(R) if (isForwardRange!R && !isInfinite!R);
templateCycle
(R) if (isInfinite!R)
structCycle
(R) if (isStaticArray!R);
autocycle
(R)(Rinput
)
if (isInputRange!R);
Cycle!Rcycle
(R)(Rinput
, size_tindex
= 0)
if (isRandomAccessRange!R && !isInfinite!R);
@system Cycle!Rcycle
(R)(ref Rinput
, size_tindex
= 0)
if (isStaticArray!R); - 与えられた前方の範囲を無限に繰り返す。元の範囲が 無限である場合(
Cycle
同一アプリケーションとなる)場合、Cycle
それを検知し、自身を範囲型にエイリアスします。 これは順方向の範囲以外でも機能します。 元の範囲がランダムアクセス可能であれば、Cycle
ランダムアクセスを提供し、 また、初期位置を受け取るコンストラクタも提供するindex
。Cycle
、パフォーマンス上の理由から、範囲に加えて静的配列にも対応している。注釈 入力範囲は空であってはならない。
circular buffer循環バッファヒント これは、単純な循環バッファを実装する素晴らしい方法である。
Examples:import std.algorithm.comparison : equal; import std.range : cycle, take; // ここでは、[1, 2]から無限循環数列を作成し // (つまり、[1, 2, 1, 2, 1, 2など]を取得する)、 // この数列から5つの要素をを取得して(つまり、[1, 2, 1, 2, 1]となる)、 // それらを等価であると期待される値と比較する。 assert(cycle([1, 2]).take(5).equal([ 1, 2, 1, 2, 1 ]));
- this(R
input
, size_tindex
= 0);
@property ref autofront
();
const @property ref autofront
();
@property voidfront
(ElementType!Rval
);
enum boolempty
;
voidpopFront
();
ref autoopIndex
(size_tn
);
const ref autoopIndex
(size_tn
);
voidopIndexAssign
(ElementType!Rval
, size_tn
);
@property Cyclesave
();
enum autoopDollar
;
autoopSlice
(size_ti
, size_tj
);
autoopSlice
(size_ti
, DollarToken); - 範囲のプリミティブ
- struct
Zip
(Ranges...) if (Ranges.length && allSatisfy!(isInputRange, Ranges));
autozip
(Ranges...)(Rangesranges
)
if (Ranges.length && allSatisfy!(isInputRange, Ranges));
autozip
(Ranges...)(StoppingPolicysp
, Rangesranges
)
if (Ranges.length && allSatisfy!(isInputRange, Ranges)); - 複数の範囲をロックステップで反復する。要素型はプロキシタプルであり、n番目の範囲の現在の要素にアクセスするには、e[n] を使用する。
zip
はxml-ph-0000@deepl.internalに似ているが、 lockstepが、lockstep は 要素を束ねず、opApply プロトコルを使用する。 lockstep は、foreach 回の反復で要素への参照アクセスを許可する。Parameters:StoppingPolicy sp
zip
範囲の長さが異なる場合の動作を制御するRanges ranges
zipで結合する Returns:少なくとも、入力範囲。Zip
すべてのコンポーネントの中で最も低いレンジ機能を提供する。 例えば、すべてのレンジがランダムアクセスを提供している場合にのみ、ランダムアクセスを提供する。また、すべてのレンジが提供している場合にのみ、変更や交換も提供する。 このため、Zip
複数の範囲を同時に操作できるため、非常に強力である。Throws:制限事項 xml-ph-0000@deepl.internal および xml-ph-0001@deepl.internal 属性は推測できない。すべての範囲の長さが同じでない場合、Exception がsp
StoppingPolicy.requireSameLength に設定されている。xml-ph-0000@deepl.internalxml-ph-0000@deepl.internal制限事項@nogc およびnothrow 属性は、 struct に対して推論できない。
Zip
実行時に異なる可能性があるため、 StoppingPolicy実行時に変化する可能性があるためです。この 制限は、xml-ph-0000@deepl.internal を引数として明示的に指定されていない場合に、zip
StoppingPolicy を引数として指定しない場合、関数によって返される匿名の範囲にはこの制限は適用されない。Examples:xml-ph-0000@deepl.internalxml-ph-0000@deepl.internalimport std.algorithm.comparison : equal; import std.algorithm.iteration : map; // pairwise sum auto arr = only(0, 1, 2); auto part1 = zip(arr, arr.dropOne).map!"a[0] + a[1]"; assert(part1.equal(only(1, 3)));
Examples:import std.conv : to; int[] a = [ 1, 2, 3 ]; string[] b = [ "a", "b", "c" ]; string[] result; foreach (tup; zip(a, b)) { result ~= tup[0].to!string ~ tup[1]; } writeln(result); // ["1a", "2b", "3c"] size_t idx = 0; // foreachでタプル要素を展開する foreach (e1, e2; zip(a, b)) { writeln(e1); // a[idx] writeln(e2); // b[idx] ++idx; }
Examples: 強力である。次のコードは、2つの配列を並行してソートする。オブジェクトを構築する。通常、これは間接的に使用することで呼び出されるzip
強力である。次のコードは、2つの配列を並列でソートする。import std.algorithm.sorting : sort; int[] a = [ 1, 2, 3 ]; string[] b = [ "a", "c", "b" ]; zip(a, b).sort!((t1, t2) => t1[0] > t2[0]); writeln(a); // [3, 2, 1] // bはaのソートに従ってソートされる writeln(b); // ["b", "c", "a"]
parallel並列- this(R
rs
, StoppingPolicys
= StoppingPolicy.shortest); - オブジェクトを構築する。通常、これは関数を使用して間接的に呼び出される zip関数を使用して間接的に呼び出される。
- enum bool
empty
; - 範囲が末尾の場合、true を返す。テストは 停止ポリシーに依存する。
- @property Zip
save
(); - @property ElementType
front
(); - 現在の反復処理対象の要素を返す。
- @property void
front
(ElementTypev
); - 反復処理されるすべての範囲の先頭を設定する。
- ElementType
moveFront
(); - 先頭の要素を削除する。
- @property ElementType
back
(); - 右端の要素を返す。
- ElementType
moveBack
(); - 後ろを移動する。右端の要素を返す。
- @property void
back
(ElementTypev
); - 現在の反復処理中の要素を返す。右端の要素を返す。
- void
popFront
(); - すべての制御された範囲で次の要素に進む。
- void
popBack
(); popBack
すべての制御された範囲を呼び出す。- @property auto
length
(); - この範囲の長さを返す。すべての範囲が定義されている場合にのみ定義される
length
。 - alias
opDollar
= length; - この範囲の長さを返す。すべての範囲が定義されている場合にのみ定義される length 。
- auto
opSlice
(size_tfrom
, size_tto
); - 範囲のスライスを返す。すべての範囲でスライスが定義されている場合のみ定義される。
- ElementType
opIndex
(size_tn
); n
複合範囲の第th要素を返す。すべての 範囲がランダムアクセス可能である場合に定義される。- void
opIndexAssign
(ElementTypev
, size_tn
); - 複合範囲の
n
複合範囲の第 番目の要素に割り当てる。すべての範囲がランダムアクセス可能である場合に定義される。合成範囲のn
複合範囲の第 番目の要素を返す。すべての範囲がランダムアクセス可能である場合に定義される。 - ElementType
moveAt
(size_tn
); - 複合範囲の
n
複合範囲の 番目の要素を読み取る。すべての範囲がランダムアクセス可能である場合に定義される。n
複合範囲の 番目の要素を返す。すべての範囲がランダムアクセス可能である場合に定義される。
- enum
StoppingPolicy
: int; - range範囲Examples:
import std.algorithm.comparison : equal; import std.exception : assertThrown; import std.range.primitives; import std.typecons : tuple; auto a = [1, 2, 3]; auto b = [4, 5, 6, 7]; auto shortest = zip(StoppingPolicy.shortest, a, b); assert(shortest.equal([ tuple(1, 4), tuple(2, 5), tuple(3, 6) ])); auto longest = zip(StoppingPolicy.longest, a, b); assert(longest.equal([ tuple(1, 4), tuple(2, 5), tuple(3, 6), tuple(0, 7) ])); auto same = zip(StoppingPolicy.requireSameLength, a, b); same.popFrontN(3); assertThrown!Exception(same.popFront);
shortest
- 最も短い範囲がすべて処理された時点で停止する
longest
- 最長の範囲が尽きた時点で停止する
requireSameLength
- すべての範囲が等しいことを要求する
- struct
Lockstep
(Ranges...) if (Ranges.length > 1 && allSatisfy!(isInputRange, Ranges));
Lockstep!Rangeslockstep
(Ranges...)(Rangesranges
)
if (allSatisfy!(isInputRange, Ranges));
Lockstep!Rangeslockstep
(Ranges...)(Rangesranges
, StoppingPolicys
)
if (allSatisfy!(isInputRange, Ranges)); - foreach ループを使用して、複数の範囲をロックステップで反復する。 zip、その要素への参照アクセスが可能である。単一の 範囲のみが渡された場合、
Lockstep
エイリアスが作成される。 範囲の長さが異なると、s
StoppingPolicy.shortest 短い方の範囲が空になった時点で終了する。範囲の長さが異なりs
StoppingPolicy.requireSameLength の場合は、例外をスローする 。s
StoppingPolicy.longest ではない可能性があり、これを渡すと 例外がスローされる。反復処理をLockstep
逆順でインデックス付きで反復処理できるのは、s
StoppingPolicy.requireSameLength の場合のみ、インデックスを維持するために 可能である。逆順で反復しようとした場合、s
StoppingPolicy.shortest例外がスローされます。 デフォルトでは、StoppingPolicy はStoppingPolicy.shortest に設定されています。制限事項 pure 、@safe 、@nogc 、またはnothrow の属性は、 反復を推測できない。
lockstep
。 zip最初の2つは、実装が異なるため推測できる。See Also: xml-ph-0000@deepl.internalExamples:auto arr1 = [1,2,3,4,5,100]; auto arr2 = [6,7,8,9,10]; foreach (ref a, b; lockstep(arr1, arr2)) { a += b; } writeln(arr1); // [7, 9, 11, 13, 15, 100] /// Lockstepは、インデックス変数を使用した反復処理もサポートしている: foreach (index, a, b; lockstep(arr1, arr2)) { writeln(arr1[index]); // a writeln(arr2[index]); // b }
- this(R
ranges
, StoppingPolicysp
= StoppingPolicy.shortest);
- struct
Recurrence
(alias fun, StateType, size_t stateSize);
Recurrence!(fun, CommonType!State, State.length)recurrence
(alias fun, State...)(Stateinitial
); - 初期値と、既存の値から次の値を計算する再帰関数を与えられた数学的シーケンスを作成する。 シーケンスは無限の順方向の範囲の形式で得られる。 "型"自体は直接使用されることはほとんどなく、 ほとんどの場合、再帰は関数xml-ph-0000@deepl.internalを呼び出すことで得られる。
Recurrence
それ自体は直接使用されることはほとんどなく、 通常は関数recurrence を呼び出すことで再帰が取得される。呼び出す際には、state状態recurrence
、次の値を計算する関数が テンプレート引数として指定され、再帰の初期値が通常の引数として渡される。例えば、 フィボナッチ数列では、初期値は2つ(したがって 状態サイズは2)である。なぜなら、次のフィボナッチ値を計算するには 過去2つの値が必要だからである。 この関数のシグネチャは次のようになる。auto fun(R)(R state, size_t n)
ここで、n は現在の値のインデックス、state は 配列インデックス記法でインデックス化できる不明瞭な状態ベクトルstate[i] となる。i の有効な値の範囲は、(n - 1) から(n - State.length) である。 関数が文字列形式で渡された場合、状態の名前は"a"、 再帰のゼロベースのインデックスの名前は"n" となる。 与えられた文字列は、a[n] に対して、a[n - 1] 、a[n - 2] 、a[n - 3] 、...、a[n - stateSize] を与えた場合に、目的の値を返さなければならない。 状態のサイズは、呼び出しに渡された引数の数によって決まる。recurrence
。Recurrence
構造体自体が 再帰の状態を管理し、適切にシフトさせる。Examples:import std.algorithm.comparison : equal; // 文字列形式の関数を使用したフィボナッチ数: // a[0] = 1、a[1] = 1、a[n+1] = a[n-1] + a[n]を計算する auto fib = recurrence!("a[n-1] + a[n-2]")(1, 1); assert(fib.take(10).equal([1, 1, 2, 3, 5, 8, 13, 21, 34, 55])); // ラムダ形式の関数を使用した階乗: auto fac = recurrence!((a,n) => a[n-1] * n)(1); assert(take(fac, 10).equal([ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 ])); // 明示的な形式で関数を使用する三角数: static size_t genTriangular(R)(R state, size_t n) { return state[n-1] + n; } auto tri = recurrence!genTriangular(0); assert(take(tri, 10).equal([0, 1, 3, 6, 10, 15, 21, 28, 36, 45]));
- struct
Sequence
(alias fun, State);
autosequence
(alias fun, State...)(Stateargs
); Sequence
Recurrence と似ているが、反復処理が いわゆる閉形式で提示されている点が異なる。つまり、n番目の要素は 初期値とn 自体から直接計算できる。これは 、 が提供するインターフェースがSequence
ランダムアクセス可能な範囲であることを意味する 。通常のRecurrence は順方向の反復のみを提供するのに対し、シーケンスの状態はTuple として保存されるため、 異種混合が可能となる。Examples: 文字列形式の関数を使用して奇数番号:文字列形式の関数を使用して奇数:auto odds = sequence!("a[0] + n * a[1]")(1, 2); writeln(odds.front); // 1 odds.popFront(); writeln(odds.front); // 3 odds.popFront(); writeln(odds.front); // 5
Examples:三角数、ラムダ形式の関数を使用:auto tri = sequence!((a,n) => n*(n+1)/2)(); // ランダムアクセスに注意 writeln(tri[0]); // 0 writeln(tri[3]); // 6 writeln(tri[1]); // 1 writeln(tri[4]); // 10 writeln(tri[2]); // 3
Examples: フィボナッチ数、関数を使用した明示的な形式:フィボナッチ数、明示的な形式の関数を使用:import std.math.exponential : pow; import std.math.rounding : round; import std.math.algebraic : sqrt; static ulong computeFib(S)(S state, size_t n) { // ビネの公式 return cast(ulong)(round((pow(state[0], n+1) - pow(state[1], n+1)) / state[2])); } auto fib = sequence!computeFib( (1.0 + sqrt(5.0)) / 2.0, // 黄金比 (1.0 - sqrt(5.0)) / 2.0, // 黄金比の共役 sqrt(5.0)); // 演算子[]によるランダムアクセスに注意 writeln(fib[1]); // 1 writeln(fib[4]); // 5 writeln(fib[3]); // 3 writeln(fib[2]); // 2 writeln(fib[9]); // 55
lambda formラムダ形式- auto
iota
(B, E, S)(Bbegin
, Eend
, Sstep
)
if ((isIntegral!(CommonType!(B, E)) || isPointer!(CommonType!(B, E))) && isIntegral!S);
autoiota
(B, E)(Bbegin
, Eend
)
if (isFloatingPoint!(CommonType!(B, E)));
autoiota
(B, E)(Bbegin
, Eend
)
if (isIntegral!(CommonType!(B, E)) || isPointer!(CommonType!(B, E)));
autoiota
(E)(Eend
)
if (is(typeof(iota
(E(0),end
))));
autoiota
(B, E, S)(Bbegin
, Eend
, Sstep
)
if (isFloatingPoint!(CommonType!(B, E, S)));
autoiota
(B, E)(Bbegin
, Eend
)
if (!isIntegral!(CommonType!(B, E)) && !isFloatingPoint!(CommonType!(B, E)) && !isPointer!(CommonType!(B, E)) && is(typeof((ref B b) { ++b; } )) && (is(typeof(B.init < E.init)) || is(typeof(B.init == E.init)))); - 指定された開始値と終了値にまたがる値の範囲を作成する 。Parameters: 開始値。
B begin
開始値。 E end
停止基準となる値。この値は 範囲には含まれない。 S step
現在の値に、反復ごとに追加する値。 Returns: 数値の範囲数値begin
、begin + step 、begin + 2 * step 、... 、最大値まで、ただしend
。 2つの引数を持つオーバーロードはstep = 1 である。begin < end && step < 0 、begin > end && step > 0 、またはbegin == end の場合、空の範囲が 返される。step == 0 の場合、begin == end はエラーとなる。 組み込み型の場合、返される範囲はランダムアクセス範囲である。 ++ をサポートするユーザー定義型の場合、範囲は入力 範囲である。 整数型イオタは、右側からin 演算子もサポートしている。 これは、ステップを考慮し、 範囲の連続する2つの値の間に含まれる場合、その値は含まれないとみなされる。 contains は、inと同じことを行うが、左側から行う。example例例
void main() { import std.stdio; // 以下のグループはすべて、同じ出力を生成する: // 0 1 2 3 4 foreach (i; 0 .. 5) writef("%s ", i); writeln(); import std.range : iota; foreach (i; iota(0, 5)) writef("%s ", i); writeln(); writefln("%(%s %|%)", iota(0, 5)); import std.algorithm.iteration : map; import std.algorithm.mutation : copy; import std.format; iota(0, 5).map!(i => format("%s ", i)).copy(stdout.lockingTextWriter()); writeln(); }
example例Examples:example例import std.algorithm.comparison : equal; import std.math.operations : isClose; auto r = iota(0, 10, 1); assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); assert(3 in r); assert(r.contains(3)); //同上 assert(!(10 in r)); assert(!(-8 in r)); r = iota(0, 11, 3); assert(equal(r, [0, 3, 6, 9])); writeln(r[2]); // 6 assert(!(2 in r)); auto rf = iota(0.0, 0.5, 0.1); assert(isClose(rf, [0.0, 0.1, 0.2, 0.3, 0.4]));
- enum
TransverseOptions
: int; - の範囲
のオプション (下記)。Examples:import std.algorithm.comparison : equal; import std.exception : assertThrown; auto arr = [[1, 2], [3, 4, 5]]; auto r1 = arr.frontTransversal!(TransverseOptions.assumeJagged); assert(r1.equal([1, 3])); // constructionにスロー assertThrown!Exception(arr.frontTransversal!(TransverseOptions.enforceNotJagged)); auto r2 = arr.frontTransversal!(TransverseOptions.assumeNotJagged); assert(r2.equal([1, 3])); // 等しい長さを仮定するか確認すると、 // 結果はランダムアクセス可能な範囲になる writeln(r2[0]); // 1 static assert(!__traits(compiles, r1[0]));
assumeJagged
- 横断された場合
- 範囲の要素は 異なる長さを持つと想定される(例えばギザギザ配列
enforceNotJagged
- 横断は
- 、
- 範囲の要素が
- すべて
- 同じ長さであることを強制する(例えば、すべて同じ長さの配列の配列)。 チェックは、横断範囲が構築された時点で一度だけ実行される 。
assumeNotJagged
- 横断は、検証を行わずに、範囲の要素がすべて同じ長さであると仮定する 。 このオプションは、 範囲の外部でチェックがすでに実行されている場合に有用である
。- struct
FrontTransversal
(Ror, TransverseOptions opt = TransverseOptions.assumeJagged);
FrontTransversal!(RangeOfRanges, opt)frontTransversal
(TransverseOptions opt = TransverseOptions.assumeJagged, RangeOfRanges)(RangeOfRangesrr
); - 範囲の集合が与えられた場合、囲まれた各範囲の最初の要素を横断的に反復する。Examples:
import std.algorithm.comparison : equal; int[][] x = new int[][2]; x[0] = [1, 2]; x[1] = [3, 4]; auto ror = frontTransversal(x); assert(equal(ror, [ 1, 3 ][]));
- this(RangeOfRanges
input
);
- 入力からの構築
- enum bool
empty
;
@property ref autofront
();
ElementTypemoveFront
();
voidpopFront
();
- 順方向範囲プリミティブ
- @property FrontTransversal
save
();
- このfrontTransversal を複製する。 注釈: 複製されるのは、 範囲のカプセル化された範囲のみである。 基礎となる範囲は複製されない
- @property ref auto
back
();
voidpopBack
();
ElementTypemoveBack
();
- 双方向プリミティブ。 isBidirectionalRange!RangeOfRanges の場合に提供される
- ref auto
opIndex
(size_tn
);
ElementTypemoveAt
(size_tn
);
voidopIndexAssign
(ElementTypeval
, size_tn
); - ラン
- ダムアクセスプリミティブ。 isRandomAccessRange!RangeOfRanges && (opt == TransverseOptions.assumeNotJagged || opt == TransverseOptions.enforceNotJagged) が提供されている場合、
- 提供される
。
- typeof(this)
opSlice
(size_tlower
, size_tupper
);
- スライシング。RangeOfRanges がスライシングをサポートしており、 インデックス作成をサポートするためのすべての条件が満たされている場合、提供される
。- struct
Transversal
(Ror, TransverseOptions opt = TransverseOptions.assumeJagged);
Transversal!(RangeOfRanges, opt)transversal
(TransverseOptions opt = TransverseOptions.assumeJagged, RangeOfRanges)(RangeOfRangesrr
, size_tn
); - 範囲の集合が与えられた場合、。
n
番目の要素を囲む各範囲について、横断的に反復する。この関数は、 他の言語におけるunzip と類似しているParameters:opt 関数が想定する範囲の長さを制御する RangeOfRanges rr
ランダムアクセス可能な範囲の入力範囲 Returns:。最小限、入力範囲。双方向性やランダムアクセスなどの範囲のプリミティブは、rr
の要素型がそれらを提供している場合に与えられるExamples:import std.algorithm.comparison : equal; int[][] x = new int[][2]; x[0] = [1, 2]; x[1] = [3, 4]; auto ror = transversal(x, 1); assert(equal(ror, [ 2, 4 ]));
Examples: - 以下のコードは完全な展開を行う。
import std.algorithm.comparison : equal; import std.algorithm.iteration : map; int[][] y = [[1, 2, 3], [4, 5, 6]]; auto z = y.front.walkLength.iota.map!(i => transversal(y, i)); assert(equal!equal(z, [[1, 4], [2, 5], [3, 6]]));
- this(RangeOfRanges
input
, size_tn
);
- 入力とインデックスからの構築。
- enum bool
empty
;
@property ref autofront
();
EmoveFront
();
@property voidfront
(Eval
);
voidpopFront
();
@property typeof(this)save
(); - 順方向のレンジプリミティブ。
- @property ref auto
back
();
voidpopBack
();
EmoveBack
();
@property voidback
(Eval
); - 双方向のプリミティブ。 isBidirectionalRange!RangeOfRanges が提供されている場合、
- これらが提供される
。
- ref auto
opIndex
(size_tn
);
EmoveAt
(size_tn
);
voidopIndexAssign
(Eval
, size_tn
); - ランダムアクセスのプリミティブ。 isRandomAccessRange!RangeOfRanges && (opt == TransverseOptions.assumeNotJagged || opt == TransverseOptions.enforceNotJagged) が提供されている場合、これらが提供される
。
- typeof(this)
opSlice
(size_tlower
, size_tupper
); - スライシング。RangeOfRanges がスライシングをサポートしており、 インデックス作成をサポートするためのすべての条件が満たされている場合、これらが提供される
。- Transposed!(RangeOfRanges, opt)
transposed
(TransverseOptions opt = TransverseOptions.assumeJagged, RangeOfRanges)(RangeOfRangesrr
)
if (isForwardRange!RangeOfRanges && isInputRange!(ElementType!RangeOfRanges) && hasAssignableElements!RangeOfRanges); - 範囲の集合が与えられた場合、i番目の部分範囲が 元の部分範囲のi番目の要素を含むような、
範囲の 集合を返す。
- Parameters:
opt 関数が想定する範囲の長さ(ギザギザがあるかないか)を制御する RangeOfRanges rr
範囲の集合 - Examples:
import std.algorithm.comparison : equal; int[][] ror = [ [1, 2, 3], [4, 5, 6] ]; auto xp = transposed(ror); assert(equal!"a.equal(b)"(xp, [ [1, 4], [2, 5], [3, 6] ]));
Examples:int[][] x = new int[][2]; x[0] = [1, 2]; x[1] = [3, 4]; auto tr = transposed(x); int[][] witness = [ [ 1, 3 ], [ 2, 4 ] ]; uint i; foreach (e; tr) { writeln(array(e)); // witness[i++] }
- struct
Indexed
(Source, Indices) if (isRandomAccessRange!Source && isInputRange!Indices && is(typeof(Source.init[ElementType!Indices.init])));
Indexed!(Source, Indices)indexed
(Source, Indices)(Sourcesource
, Indicesindices
); - この構造体は、。
source
とindices
の2つの範囲を受け取り、source
のビューを作成する。その要素は、indices
に従って並べ替えられたかのように。indices
は、source
の要素のサブセットのみを含み、 要素が繰り返される場合もあるSource はランダムアクセス可能な範囲でなければならない。返される範囲は、Indices が双方向またはランダムアクセスの場合は、それぞれ双方向またはランダムアクセスとなる。Examples:import std.algorithm.comparison : equal; auto source = [1, 2, 3, 4, 5]; auto indices = [4, 3, 1, 2, 0, 4]; auto ind = indexed(source, indices); assert(equal(ind, [5, 4, 2, 3, 1, 5])); assert(equal(retro(ind), [5, 1, 3, 2, 4, 5]));
- @property ref auto
front
();
voidpopFront
();
@property typeof(this)save
();
@property ref autofront
(ElementType!SourcenewVal
);
automoveFront
();
@property ref autoback
();
voidpopBack
();
@property ref autoback
(ElementType!SourcenewVal
);
automoveBack
();
ref autoopIndex
(size_tindex
);
typeof(this)opSlice
(size_ta
, size_tb
);
autoopIndexAssign
(ElementType!SourcenewVal
, size_tindex
);
automoveAt
(size_tindex
); - 範囲のプリミティブ
- @property Source
source
(); - ソース範囲を返す。
- @property Indices
indices
(); - インデックス範囲を返す
。
- size_t
physicalIndex
(size_tlogicalIndex
);
- 指定された論理インデックスに対応するソース範囲の物理インデックスを返す。 これは、例えば、Indexed にインデックスを付ける際に、別の間接レイヤーを追加せずに使用できる。Examples:
auto ind = indexed([1, 2, 3, 4, 5], [1, 3, 4]); writeln(ind.physicalIndex(0)); // 1
- struct
Chunks
(Source) if (isInputRange!Source);
Chunks!Sourcechunks
(Source)(Sourcesource
, size_tchunkSize
)
if (isInputRange!Source); - !isInfinite!Source と
source
.walkLength均等に割り切れない 場合、chunkSize
場合、この範囲の後ろの要素には 要素が不足することになりますchunkSize
。 Source が前方範囲の場合、結果として得られる範囲も前方範囲となる。 それ以外の場合、結果として得られるチャンクは、同じ入力範囲を消費する入力範囲となる。front を繰り返し実行すると、チャンクが縮小され、front のその後の呼び出しではチャンク全体が返されなくなる。また、popFront を外側の範囲で呼び出すと、front の以前の値への残存する参照がすべて無効になる。Parameters:Source source
チャンクが選択される範囲 size_t chunkSize
チャンクサイズ See Also:Returns: チャンクの範囲。range範囲チャンクの範囲。Examples:range of chunksチャンクの範囲import std.algorithm.comparison : equal; auto source = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; auto chunks = chunks(source, 4); writeln(chunks[0]); // [1, 2, 3, 4] writeln(chunks[1]); // [5, 6, 7, 8] writeln(chunks[2]); // [9, 10] writeln(chunks.back); // chunks[2] writeln(chunks.front); // chunks[0] writeln(chunks.length); // 3 assert(equal(retro(array(chunks)), array(retro(chunks))));
Examples: 非順方向の入力範囲はサポートされているが、限定的なセマンティクスとなる。non-forward input range非順方向入力範囲非順方向の入力範囲はサポートされているが、限定的なセマンティクスとなる。import std.algorithm.comparison : equal; int i; // ジェネレータは状態を保存しないので、順方向の範囲にはできない。 auto inputRange = generate!(() => ++i).take(10); // まだチャンク単位で処理することはできるが、シングルパスのみとなる。 auto chunked = inputRange.chunks(2); assert(chunked.front.equal([1, 2])); assert(chunked.front.empty); // チャンクを繰り返すと、それが消費される chunked.popFront; assert(chunked.front.equal([3, 4]));
range範囲- this(Source
source
, size_tchunkSize
); - 標準コンストラクタ
- @property auto
front
();
voidpopFront
();
@property boolempty
(); - 入力範囲のプリミティブ。常に存在する。
- @property typeof(this)
save
(); - 前方範囲のプリミティブ。Source が前方範囲の場合のみ存在する。
- @property size_t
length
(); - 長さ。hasLength!Source が長さの場合のみtrue
- auto
opIndex
(size_tindex
);
typeof(this)opSlice
(size_tlower
, size_tupper
); - インデックスおよびスライス操作。hasSlicing!Source がtrue の場合のみ提供される。
- @property auto
back
();
voidpopBack
(); - 双方向の範囲のプリミティブ。 hasSlicing!Source とhasLength!Source がtrue の場合のみ提供される。
- struct
EvenChunks
(Source) if (isForwardRange!Source && hasLength!Source);
EvenChunks!SourceevenChunks
(Source)(Sourcesource
, size_tchunkCount
)
if (isForwardRange!Source && hasLength!Source); - この範囲は、
source
範囲をchunkCount
ほぼ同じ長さの まとまりに分割します。Source は、 長さが既知のchunks、emailemailevenChunks
チャンクの数(サイズではない)を受け取る。 返される範囲には、source.length / chunkCount + 1 要素が0個以上含まれ、その後ろにsource.length / chunkCount 要素が続く。source.length < chunkCount の場合、一部のチャンクは空になる。chunkCount
ゼロにしてはならない。ただし、source
それも空の場合を除いては。Examples:import std.algorithm.comparison : equal; auto source = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; auto chunks = evenChunks(source, 3); writeln(chunks[0]); // [1, 2, 3, 4] writeln(chunks[1]); // [5, 6, 7] writeln(chunks[2]); // [8, 9, 10]
- this(Source
source
, size_tchunkCount
); - 標準コンストラクタ
- @property auto
front
();
voidpopFront
();
@property boolempty
();
@property typeof(this)save
(); - 前方範囲のプリミティブ。常に存在する。
- const @property size_t
length
(); - 長さ
- auto
opIndex
(size_tindex
);
typeof(this)opSlice
(size_tlower
, size_tupper
);
@property autoback
();
voidpopBack
(); - インデックス、スライス、双方向操作、および範囲のプリミティブ。hasSlicing!Source がtrue の場合のみ提供される。
- auto
slide
(Flag!"withPartial" f = Yes.withPartial, Source)(Sourcesource
, size_twindowSize
, size_tstepSize
= 1)
if (isForwardRange!Source); - 固定サイズのスライディングウィンドウの反復 サイズ
windowSize
source
範囲で、カスタムのstepSize
。Source の範囲は少なくともForwardRangeでなければならず、ititwindowSize
ゼロより大きい値でなければなりません。 ForwindowSize
= 1範囲を単一要素グループに分割する(別名unflatten )。windowSize
= 2それは似ている。 zip(source
,source
.save.dropOne)。Parameters:f 最後の要素が本来あるべきよりも少ない要素数であるかどうかは、 windowSize
無視される(No.withPartial )か、追加される(Yes.withPartial )かSource source
スライドが選択される範囲 size_t windowSize
スライディングウィンドウのサイズ size_t stepSize
ウィンドウ間のステップ(デフォルトでは1) Returns:双方向性、順方向、ランダムアクセス、スライスを伝搬させたすべてのスライディングウィンドウの範囲。注釈 パフォーマンスのオーバーヘッドを避けるため、双方向性は 以下の条件を満たす場合のみ利用可能である std.range.primitives.hasSlicing かつ std.range.primitives.hasLengthが真の場合のみです。
See Also:Examples: ウィンドウを使用して範囲を繰り返すウィンドウ付きの範囲を繰り返し処理するimport std.algorithm.comparison : equal; assert([0, 1, 2, 3].slide(2).equal!equal( [[0, 1], [1, 2], [2, 3]] )); assert(5.iota.slide(3).equal!equal( [[0, 1, 2], [1, 2, 3], [2, 3, 4]] ));
range範囲Examples: ステップサイズをカスタム設定する(デフォルトは1)カスタムステップサイズを設定する(デフォルトは1)import std.algorithm.comparison : equal; assert(6.iota.slide(1, 2).equal!equal( [[0], [2], [4]] )); assert(6.iota.slide(2, 4).equal!equal( [[0, 1], [4, 5]] )); assert(iota(7).slide(2, 2).equal!equal( [[0, 1], [2, 3], [4, 5], [6]] )); assert(iota(12).slide(2, 4).equal!equal( [[0, 1], [4, 5], [8, 9]] ));
stepsizestepsizeExamples: 最後のスライドには、windowSizeよりも少ない要素を使用する最後のスライドには、windowSizeよりも少ない要素を使用するimport std.algorithm.comparison : equal; assert(3.iota.slide!(No.withPartial)(4).empty); assert(3.iota.slide!(Yes.withPartial)(4).equal!equal( [[0, 1, 2]] ));
windowSizewindowSizeExamples: 長さ2のすべての可能な部分文字列を数える長さ2のすべての可能な部分文字列を数えるimport std.algorithm.iteration : each; int[dstring] d; "AGAGA"d.slide!(Yes.withPartial)(2).each!(a => d[a]++); writeln(d); // ["AG"d:2, "GA"d:2]
substringsubstringExamples: withPartialは、範囲の最後の要素が完全なサイズを持たない場合にのみ効果があるwithPartialは、範囲の最後の要素が完全なサイズでない場合にのみ効果があるimport std.algorithm.comparison : equal; assert(5.iota.slide!(Yes.withPartial)(3, 4).equal!equal([[0, 1, 2], [4]])); assert(6.iota.slide!(Yes.withPartial)(3, 4).equal!equal([[0, 1, 2], [4, 5]])); assert(7.iota.slide!(Yes.withPartial)(3, 4).equal!equal([[0, 1, 2], [4, 5, 6]])); assert(5.iota.slide!(No.withPartial)(3, 4).equal!equal([[0, 1, 2]])); assert(6.iota.slide!(No.withPartial)(3, 4).equal!equal([[0, 1, 2]])); assert(7.iota.slide!(No.withPartial)(3, 4).equal!equal([[0, 1, 2], [4, 5, 6]]));
length長さ - auto
only
(Values...)(return scope Valuesvalues
)
if (!is(CommonType!Values == void));
autoonly
()(); values
すべての要素をその場で保持する範囲にまとめる。単一の値または複数の離散した値を 範囲を想定しているアルゴリズムに渡す必要がある場合、動的メモリ割り当てを実行することなく 使用できる。 範囲をコピーするとすべての要素がコピーされるため、 関数から安全に返すことができる。同じ理由で、 返された範囲をコピーすると、引数の数が多い場合にはコストが高くなる可能性がある。 "function"関数rangerangeParameters:Values values
一緒に組み立てるべき値 Returns: 組み立てられた値のxml-ph-0000@deepl.internal。xml-ph-0001@deepl.internal 返された範囲はスライスすることができる。その要素は代入することができる。組み立てられた値のRandomAccessRange 。 返された範囲はスライスすることができる。その要素は、Values 内のすべての型が範囲の要素型からの代入をサポートしている場合、See Also:rangerangechain範囲を連結するExamples:import std.algorithm.comparison : equal; import std.algorithm.iteration : filter, joiner, map; import std.algorithm.searching : findSplitBefore; import std.uni : isUpper; assert(equal(only('♡'), "♡")); writeln([1, 2, 3, 4].findSplitBefore(only(3))[0]); // [1, 2] assert(only("one", "two", "three").joiner(" ").equal("one two three")); string title = "The D Programming Language"; assert(title .filter!isUpper // 大文字を取る .map!only // 各文字をそれぞれの範囲にする .joiner(".") // のんびりと範囲を結合する .equal("T.D.P.L"));
- auto
enumerate
(Enumerator = size_t, Range)(Rangerange
, Enumeratorstart
= 0)
if (isIntegral!Enumerator && isInputRange!Range); - 添え字変数を付けて繰り返し処理を行う。
range
添え字変数を付けて各要素は、 std.typecons.Tupleインデックスと 要素が順に含まれており、インデックスのメンバーはindex、 要素のメンバーはvalue という名前である。 インデックスはstart
、反復ごとに1ずつインクリメントされる。オーバーフロー もし
もしrange
長さがある場合、"so"に値を渡すことはエラーです。start
ので、start
+range
.lengthEnumerator.max より大きくなるため、 オーバーフローが発生しないことが保証される。range
長さがなく、popFront がfront.index == Enumerator.max のときに呼び出された場合、インデックスがオーバーフローし、Enumerator.min から継続されます。Parameters:Range range
インデックスを添付する入力範囲 Enumerator start
インデックスのカウンターを何から開始するかを指定する Returns: 少なくとも、入力範囲。他のすべての範囲の基本要素は、結果として得られる範囲に与えられる。例 xml-ph-0000@deepl.internal をインデックスループ変数とともに使用する場合に便利:少なくとも、入力範囲。他のすべての範囲のプリミティブは、 結果として得られる範囲にそれらが存在する場合に与えられるrange
。例外は双方向の 基本要素で、これはrange
長さがある場合のみ例 インデックスループ変数でforeach を使用する場合に便利:
import std.stdio : stdin, stdout; import std.range : enumerate; foreach (lineNum, line; stdin.byLine().enumerate(1)) stdout.writefln("line #%s: %s", lineNum, line);
Examples:xml-ph-0000@deepl.internalが型T1とT2の変数を任意の順序で受け入れる場合、trueを返す。 以下のコードはコンパイルできるはずである。負のポジションから列挙を開始できる:import std.array : assocArray; import std.range : enumerate; bool[int] aa = true.repeat(3).enumerate(-1).assocArray(); assert(aa[-1]); assert(aa[0]); assert(aa[1]);
index負の - enum auto
isTwoWayCompatible
(alias fn, T1, T2); - fn が型T1とT2の変数を任意の順序で受け入れる場合は、trueを返す。 以下のコードはコンパイルできるはずである。any order任意の順序
(ref T1 a, ref T2 b) { fn(a, b); fn(b, a); }
Examples:void func1(int a, int b); void func2(int a, float b); static assert(isTwoWayCompatible!(func1, int, int)); static assert(isTwoWayCompatible!(func1, short, int)); static assert(!isTwoWayCompatible!(func2, int, float)); void func3(ref int a, ref int b); static assert( isTwoWayCompatible!(func3, int, int)); static assert(!isTwoWayCompatible!(func3, short, int));
- enum
SearchPolicy
: int; - Examples:
import std.algorithm.comparison : equal; auto a = assumeSorted([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); auto p1 = a.upperBound!(SearchPolicy.binarySearch)(3); assert(p1.equal([4, 5, 6, 7, 8, 9])); auto p2 = a.lowerBound!(SearchPolicy.gallop)(4); assert(p2.equal([0, 1, 2, 3]));
linear
- 直線的に検索する。
trot
- 線形に増加するステップで検索する(1、2、3、...)。 二次探索スケジュール(試行されるインデックスは0、1、 3、6、10、15、21、28、...)につながる。探索が目標値を逸脱すると、 残りの区間は二分探索を用いて探索される。 探索はΟ(sqrt(n))時間で完了する。 "値"が範囲の開始付近にあると 十分に確信できる場合にこれを使用する。
gallop
- ギャロッピングサーチアルゴリズムを実行する。すなわち、 ステップが毎回2倍になる検索(1、2、4、8、...)を行い、 指数関数的な検索スケジュール(試行されるインデックスは0、1、3、 7、15、31、63、...)に導く。検索が目標値を上回ると、 残りの間隔は二分探索を使用して検索される。値は Ο(log(n))の時間で発見される。
binarySearch
- 古典的な間隔半減ポリシーを使用して検索する。 検索は範囲の中央から開始し、各検索ステップで 範囲が半分になる。このポリシーでは、Ο(log(n))の時間で値を見つけることができるが、 大きな範囲ではgallop よりもキャッシュに優しくない 。
binarySearch
ポリシーは、trot 、gallop 、trotBackwards 、 gallopBackwards の戦略の最後のステップとして使用される。 trotBackwards
- trot と同様だが、逆方向から開始する。 値が範囲の終わり付近にあると確信している場合にこれを使用する。
gallopBackwards
- gallop と同様だが、逆方向から開始する。 値が範囲の端付近にあると確信している場合に使う。
- enum
SortedRangeOptions
: int; - 範囲のオプション(下記) SortedRange範囲(下記)のオプション。rangerangeExamples:
// 厳密にチェックされたSortedRangeを作成する SortedRange!(int[],"a < b", SortedRangeOptions.checkStrictly)([ 1, 3, 5, 7, 9 ]);
assumeSorted
- 範囲は確認せずにソートされていると仮定する。
checkStrictly
- 範囲のすべての要素がソートされているか確認される。 確認はO(n)の時間で実行される。
checkRoughly
- 範囲の要素の一部がソートされているか確認される。 ランダムな順序を持つ範囲については、これはほぼ確実に ソートされていないことを検出する。ほぼソートされた範囲については 、失敗する可能性が高い。確認された要素は 決定論的な方法で選択されるため、この確認は再現可能である。 確認はO(log(n))時間で実行される。
- struct
SortedRange
(Range, alias pred = "a < b", SortedRangeOptions opt = SortedRangeOptions.assumeSorted) if (isInputRange!Range && !isInstanceOf!(SortedRange
, Range));
templateSortedRange
(Range, alias pred = "a < b", SortedRangeOptions opt = SortedRangeOptions.assumeSorted) if (isInstanceOf!(SortedRange
, Range)) - ソート済みの範囲を表す。通常の範囲のプリミティブに加えて、 ソートを活かした追加の操作、例えばマージや二分探索などもサポートする。 ソートされていない範囲r から SortedRange を取得するには、 std.algorithm.sorting.sortr をその場でソートし、対応するものを返す
SortedRange
。SortedRange
すでにソート済みであることがわかっている範囲 r から、 assumeSorted。Parameters:Examples:import std.algorithm.sorting : sort; auto a = [ 1, 2, 3, 42, 52, 64 ]; auto r = assumeSorted(a); assert(r.contains(3)); assert(!(32 in r)); auto r1 = sort!"a > b"(a); assert(3 in r1); assert(!r1.contains(32)); writeln(r1.release()); // [64, 52, 42, 3, 2, 1]
Examples: ランダムアクセスよりも弱い範囲を受け入れることも可能だが、それらに対して興味深い機能を提供することはできない。したがって、SortedRange
ランダムアクセスよりも弱い範囲を受け入れることも可能だが、 それらに対して興味深い機能を提供することはできない。そのため、SortedRange
現在はランダムアクセス可能な範囲に制限されている。 元の範囲のコピーは作成されない。基礎となる範囲が 対応する範囲と併せて変更された場合、SortedRange
ソート順が崩れるような 変更が加えられた場合、SortedRange
動作が不安定になります。import std.algorithm.mutation : swap; auto a = [ 1, 2, 3, 42, 52, 64 ]; auto r = assumeSorted(a); assert(r.contains(42)); swap(a[3], a[5]); // 本来の範囲パスのソートを解除することは違法だが、 assert(!r.contains(42)); // そうすべきではない
Examples: 、基礎となる範囲の2つの要素を引数として取らない述語で検索できる。xml-ph-0000@deepl.internalこれは、構造体の範囲がソートされている場合に有用である。SortedRange
基礎となる範囲の2つの要素を引数として取らない述語で検索することができます。 これは、構造体の範囲がメンバによってソートされており、 そのメンバの値のみを指定してその範囲内で検索を行いたい場合に便利です。import std.algorithm.comparison : equal; static struct S { int i; } static bool byI(A, B)(A a, B b) { static if (is(A == S)) return a.i < b; else return a < b.i; } auto r = assumeSorted!byI([S(1), S(2), S(3)]); auto lessThanTwo = r.lowerBound(2); assert(equal(lessThanTwo, [S(1)]));
emailemail- @property bool
empty
();
@property autosave
();
@property ref autofront
();
voidpopFront
();
@property ref autoback
();
voidpopBack
();
ref autoopIndex
(size_ti
);
scope autoopSlice
(size_ta
, size_tb
) return; - 範囲のプリミティブ。
- scope auto
release
() return; - 制御された範囲を解放し、それを返す。これは、その反対の動作を行う。 assumeSorted。範囲をSortedRange に変換するのではなく、SortedRangeから元の範囲を抽出する。 move.std.algorithm.mutation。xml-ph-0001@deepl.internalxml-ph-0001@deepl.internalExamples:
import std.algorithm.sorting : sort; int[3] data = [ 1, 2, 3 ]; auto a = assumeSorted(data[]); writeln(a); // sort!"a < b"(data[]) int[] p = a.release(); writeln(p); // [1, 2, 3]
- auto
lowerBound
(SearchPolicy sp = SearchPolicy.binarySearch, V)(Vvalue
)
if (isTwoWayCompatible!(predFun, ElementType!Range, V) && hasSlicing!Range); - この関数は、ポリシーsp を使用して検索を行い、 pred(x, value) がtrue となる左側の最大の部分範囲を、すべてのx について 見つける(例えば、pred が「より小さい」場合は、 要素が厳密に小さい範囲の部分を返すless than未満
value
。検索 スケジュールとその複雑性については、 SearchPolicy。Examples:import std.algorithm.comparison : equal; auto a = assumeSorted([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]); auto p = a.lowerBound(4); assert(equal(p, [ 0, 1, 2, 3 ]));
- auto
upperBound
(SearchPolicy sp = SearchPolicy.binarySearch, V)(Vvalue
)
if (isTwoWayCompatible!(predFun, ElementType!Range, V)); - この関数は、ポリシーsp に従って、pred(value, x) がtrue となる最大の右部分範囲を、 すべてのxについて検索する(例えば、pred が「未満」の場合は、 要素が厳密に「より大きい」範囲の部分を返す
value
。検索スケジュールと その複雑性については、 SearchPolicy。ランダムアクセスができない範囲については、SearchPolicy.linearのみが許可されたポリシーである(ユーザーコードが予期せぬ非効率性にさらされないよう、明示的に指定する必要がある )。ランダムアクセス検索については、すべての ポリシーが許可され、SearchPolicy.binarySearch がデフォルトである。xml-ph-0001@deepl.internalxml-ph-0001@deepl.internalExamples:import std.algorithm.comparison : equal; auto a = assumeSorted([ 1, 2, 3, 3, 3, 4, 4, 5, 6 ]); auto p = a.upperBound(3); assert(equal(p, [4, 4, 5, 6]));
- auto
equalRange
(V)(Vvalue
)
if (isTwoWayCompatible!(predFun, ElementType!Range, V) && isRandomAccessRange!Range); - e のすべての要素を含む部分範囲を返す。 pred(e, value) とpred(value, e) がともにfalse と評価される場合(例えば、 pred が「より小さい」の場合、要素が等しい範囲の部分を返す )。Omicronxml-ph-0002@deepl.internal
value
。条件を満たす値が見つかるまで、区間を半分に減らす古典的な二分探索を使用し 、その後、左境界を見つけるためにSearchPolicy.gallopBackwards を使用し、 右境界を見つけるためにSearchPolicy.gallop を使用する。 これらのポリシーは、2つの境界が 最初に発見された値の近くにある可能性が高いという事実(すなわち、等しい範囲は比較的小さい)によって正当化される。 全体の探索をΟ(log(n)) 時間で完了する。Examples:import std.algorithm.comparison : equal; auto a = [ 1, 2, 3, 3, 3, 4, 4, 5, 6 ]; auto r = a.assumeSorted.equalRange(3); assert(equal(r, [ 3, 3, 3 ]));
- auto
trisect
(V)(Vvalue
)
if (isTwoWayCompatible!(predFun, ElementType!Range, V) && isRandomAccessRange!Range && hasLength!Range); - タプルr を返す。r[0] は、 の結果と同じであり、 は の結果と同じであり、 は lowerBound(OmicronOmicron
value
)、r[1] はequalRange(value) の結果と同じであり、r[2] はupperBound(value) の結果と同じである。この呼び出しは、3つを個別に計算するよりも高速である。equalRange と同様の検索スケジュールを使用する。全体の検索を Ο(log(n)) 時間で完了する。Examples:import std.algorithm.comparison : equal; auto a = [ 1, 2, 3, 3, 3, 4, 4, 5, 6 ]; auto r = assumeSorted(a).trisect(3); assert(equal(r[0], [ 1, 2 ])); assert(equal(r[1], [ 3, 3, 3 ])); assert(equal(r[2], [ 4, 4, 5, 6 ]));
- bool
contains
(V)(Vvalue
)
if (isRandomAccessRange!Range); - true で見つかった場合のみ、 を返す。
value
range で見つかった場合のみ、 を返す。 はソート済みであると想定される。pred のΟ(log(r.length)) 評価を行う。 - bool
opBinaryRight
(string op, V)(Vvalue
)
if (op == "in" && isRandomAccessRange!Range); - contains と同様だが、値は範囲の前に指定される。
- auto
groupBy
()(); - ソート関係に従って等価な要素のサブレンジのレンジを返す。
- auto
assumeSorted
(alias pred = "a < b", R)(Rr
)
if (isInputRange!(Unqual!R)); - xml-ph-0000@deepl.internalxml-ph-0000@deepl.internal
r
述語pred によってソートされていると仮定し、 対応するSortedRange!(pred, R) をr
。 ソート済みかどうかを調べるには、 コスト Ο (n) を使用する。 std.algorithm.sorting.isSorted。Examples:import std.algorithm.comparison : equal; int[] a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; auto p = assumeSorted(a); assert(equal(p.lowerBound(4), [0, 1, 2, 3])); assert(equal(p.lowerBound(5), [0, 1, 2, 3, 4])); assert(equal(p.lowerBound(6), [0, 1, 2, 3, 4, 5])); assert(equal(p.lowerBound(6.9), [0, 1, 2, 3, 4, 5, 6]));
- struct
RefRange
(R) if (isInputRange!R);
autorefRange
(R)(R*range
)
if (isInputRange!R); - Wrapperは、参照渡しを効果的に行うことができる。 元のRangeとRefRangeは、常にまったく同じ要素を持つ。 どちらか一方に対して実行された操作は、もう一方にも影響する。例えば、 関数に渡された場合、元のRangeが暗黙的にコピーされる 場合、元のRangeはコピーされず、 参照型であるかのように消費される。
注釈 save は通常通り動作し、新しい範囲に対して操作を行う。そのため、 save が呼び出された場合、
RefRange
、保存された範囲での操作は元のファイルには影響しません。Parameters:R* range
その範囲から RefRange
Returns: AARefRange
。与えられた範囲がクラス型( したがって、すでに参照型)である場合、元の 範囲が返されるのではなく、RefRange
。Examples: 基本例基本的な例import std.algorithm.searching : find; ubyte[] buffer = [1, 9, 45, 12, 22]; auto found1 = find(buffer, 45); writeln(found1); // [45, 12, 22] writeln(buffer); // [1, 9, 45, 12, 22] auto wrapped1 = refRange(&buffer); auto found2 = find(wrapped1, 45); writeln(*found2.ptr); // [45, 12, 22] writeln(buffer); // [45, 12, 22] auto found3 = find(wrapped1.save, 22); writeln(*found3.ptr); // [22] writeln(buffer); // [45, 12, 22] string str = "hello world"; auto wrappedStr = refRange(&str); writeln(str.front); // 'h' str.popFrontN(5); writeln(str); // " world" writeln(wrappedStr.front); // ' ' writeln(*wrappedStr.ptr); // " world"
basic example基本例Examples: opAssignの例。opAssignの例。ubyte[] buffer1 = [1, 2, 3, 4, 5]; ubyte[] buffer2 = [6, 7, 8, 9, 10]; auto wrapped1 = refRange(&buffer1); auto wrapped2 = refRange(&buffer2); assert(wrapped1.ptr is &buffer1); assert(wrapped2.ptr is &buffer2); assert(wrapped1.ptr !is wrapped2.ptr); assert(buffer1 != buffer2); wrapped1 = wrapped2; //すべてが以前と同じものを指している。 assert(wrapped1.ptr is &buffer1); assert(wrapped2.ptr is &buffer2); assert(wrapped1.ptr !is wrapped2.ptr); //しかし、buffer1は割り当てにより変更された。 writeln(buffer1); // [6, 7, 8, 9, 10] writeln(buffer2); // [6, 7, 8, 9, 10] buffer2 = [11, 12, 13, 14, 15]; //すべてが以前と同じものを指している。 assert(wrapped1.ptr is &buffer1); assert(wrapped2.ptr is &buffer2); assert(wrapped1.ptr !is wrapped2.ptr); //しかし、buffer2は割り当てにより変更された。 writeln(buffer1); // [6, 7, 8, 9, 10] writeln(buffer2); // [11, 12, 13, 14, 15] wrapped2 = null; //ポインタはwrap2に対して変更されたが、wrap1に対しては変更されなかった。 assert(wrapped1.ptr is &buffer1); assert(wrapped2.ptr is null); assert(wrapped1.ptr !is wrapped2.ptr); //buffer2は代入の影響を受けない。 writeln(buffer1); // [6, 7, 8, 9, 10] writeln(buffer2); // [11, 12, 13, 14, 15]
example例- pure nothrow @safe this(R*
range
); - auto
opAssign
(RefRangerhs
); - これは、xml-ph-0000@deepl.internal のポインタを割り当てない。
rhs
このRefRange に割り当てられるわけではない。 むしろ、rhs
このRefRange が指す範囲に割り当てられる。 これは、RefRange に対するすべての操作は、 元の範囲に対して行われた場合と同じであるためである。 例外は、RefRange がnull に直接またはrhs
null である場合です。その場合、RefRangeは もはや元の範囲を指すのではなく、null となります。 - void
opAssign
(typeof(null)rhs
); - inout pure nothrow @property @safe inout(R*)
ptr
(); - 折り返された範囲へのポインタ。
- @property auto
front
();
const @property autofront
();
@property autofront
(ElementType!Rvalue
); - @property bool
empty
();
const @property boolempty
(); - void
popFront
(); - @property auto
save
();
const @property autosave
();
autoopSlice
();
const autoopSlice
(); - isForwardRange!R がtrue の場合にのみ定義される。
- @property auto
back
();
const @property autoback
();
@property autoback
(ElementType!Rvalue
);
voidpopBack
(); - isBidirectionalRange!R がtrue の場合にのみ定義される。
- ref auto
opIndex
(IndexType)(IndexTypeindex
);
const ref autoopIndex
(IndexType)(IndexTypeindex
); - isRandomAccessRange!R がtrue の場合にのみ定義される。
- auto
moveFront
(); - hasMobileElements!R とisForwardRange!R がtrue の場合のみ定義される。
- auto
moveBack
(); - hasMobileElements!R とisBidirectionalRange!Rがtrue の場合のみ定義される。
- auto
moveAt
(size_tindex
); - hasMobileElements!R とisRandomAccessRange!Rがtrue の場合のみ定義される。
- @property size_t
length
();
const @property size_tlength
();
aliasopDollar
= length; - hasLength!R がtrue の場合にのみ定義される。
- auto
opSlice
(IndexType1, IndexType2)(IndexType1begin
, IndexType2end
);
const autoopSlice
(IndexType1, IndexType2)(IndexType1begin
, IndexType2end
); - hasSlicing!R がtrue の場合にのみ定義される。
- auto
bitwise
(R)(auto ref Rrange
)
if (isInputRange!R && isIntegral!(ElementType!R)); - 整数の型範囲におけるビット単位のアダプター。範囲の要素をビット単位で、 最下位ビットから最上位ビットまでParameters:
R 整数の入力範囲を反復処理する R range
ビットずつ消費する Returns: xml-ph-0000@deepl.internal 入力範囲を順方向に伝搬させ、双方向およびランダムアクセス機能を備えたBitwise 入力範囲を順方向に伝搬し、双方向 およびランダムアクセス機能を備えたExamples:import std.algorithm.comparison : equal; import std.format : format; // 00000011 00001001 ubyte[] arr = [3, 9]; auto r = arr.bitwise; // 他の範囲と同じようにそれを反復する writeln(format("%(%d%)", r)); // "1100000010010000" assert(format("%(%d%)", r.retro).equal("1100000010010000".retro)); auto r2 = r[5 .. $]; // ビットをセットする r[2] = 1; writeln(arr[0]); // 7 writeln(r[5]); // r2[0]
Examples: ビット単位で使用することで、均一なブール値ジェネレータを実装できるビット単位で使用することで、均一なブール値ジェネレータを実装できるimport std.algorithm.comparison : equal; import std.random : rndGen; auto rb = rndGen.bitwise; static assert(isInfinite!(typeof(rb))); auto rb2 = rndGen.bitwise; // 構造体は値で渡されることをお忘れなく assert(rb.take(10).equal(rb2.take(10)));
boolbool - struct
NullSink
;
ref autonullSink
(); - 受け取ったデータを破棄するOutputRange。range範囲Examples:rangerange
import std.algorithm.iteration : map; import std.algorithm.mutation : copy; [4, 5, 6].map!(x => x * 2).copy(nullSink); // データは捨てられる
Examples:import std.csv : csvNextToken; string line = "a,b,c"; // 最初の列を無視する line.csvNextToken(nullSink, ',', '"'); line.popFront; // 2列目を見る Appender!string app; line.csvNextToken(app, ',', '"'); writeln(app.data); // "b"
- auto
tee
(Flag!"pipeOnPop" pipeOnPop = Yes.pipeOnPop, R1, R2)(R1inputRange
, R2outputRange
)
if (isInputRange!R1 && isOutputRange!(R2, ElementType!R1));
autotee
(alias fun, Flag!"pipeOnPop" pipeOnPop = Yes.pipeOnPop, R1)(R1inputRange
)
if (is(typeof(fun) == void) || isSomeFunction!fun); - 入力範囲を包み込む「ティー」スタイルのパイプを実装し、その範囲の要素を 指定された関数に渡したり、 OutputRange。これは、長い範囲のコードの連鎖の中で中間値を印刷する場合に有用である 。また、front またはpopFront への各呼び出しで副作用のある操作を実行する場合や、 補助的なものに範囲の要素を転用する場合にも OutputRange。結果として得られる範囲は遅延評価されるため、 関数を受け取るバージョンの場合、
tee
関数を受け取るバージョンでは、関数は 実際に実行されるのは、範囲を評価する関数を使用してその範囲が「処理」されるまで std.array.arrayまたは std.algorithm.iteration.fold。Parameters: xml-ph-0000@deepl.internal の場合、xml-ph-0001@deepl.internal を呼び出すことなく、単に範囲を反復するだけで十分である。pipeOnPop Yes.pipeOnPop の場合、front を呼び出すことなく、単に範囲を反復するだけで 十分である。 tee
要素をミラーリングするoutputRange
(または、 それぞれfun )。popFront() の呼び出しは、 新しい値ではなく、古いfront の値をミラーリングすることに注意。つまり、 範囲が空になるまで反復されない場合、最後の値は転送されない。No.pipeOnPop の場合、front が呼び出された要素のみがoutputRange
。fun 。同じ要素に対してfront が2回呼び出された場合でも、 送信されるのは1回のみである。このキャッシュが不要な場合は、 代わりに std.algorithm.iteration.map。R1 inputRange
渡される入力の範囲。 R2 outputRange
この範囲には、 inputRange
反復処理が進むにつれて 順次受け取ります。fun この関数は、反復処理が進むにつれて、要素が順次呼び出される inputRange
反復処理が進むにつれて、Returns:要素を提供する入力範囲inputRange
。inputRange
より強力な範囲(前方、双方向など)であるかどうかに関わらず、 結果は常に入力範囲となります。これを読み込むと、inputRange
繰り返し実行され、順番に要素が返されます。さらに、同じ要素がoutputRange
またはfun にも渡される。See Also:to xml-ph-0000@deepl.internalxml-ph-0000@deepl.internalExamples:import std.algorithm.comparison : equal; import std.algorithm.iteration : filter, map; // コピーしながら値を合計する int[] values = [1, 4, 9, 16, 25]; int sum = 0; auto newValues = values.tee!(a => sum += a).array; assert(equal(newValues, values)); writeln(sum); // 1 + 4 + 9 + 16 + 25 // 最初のフィルターを通過した値を数える int count = 0; auto newValues4 = values.filter!(a => a < 10) .tee!(a => count++) .map!(a => a + 1) .filter!(a => a < 10); //Fine。equalは、渡された遅延範囲も評価する。 //equalがnewValues4を評価するまでcountは3にならない assert(equal(newValues4, [2, 5])); writeln(count); // 3
- auto
padLeft
(R, E)(Rr
, Ee
, size_tn
)
if ((isInputRange!R && hasLength!R || isForwardRange!R) && !is(CommonType!(ElementType!R, E) == void)); - 入力範囲の長さを拡張する
r
範囲の先頭を要素で埋めることで、e
。要素はe
範囲の要素型と共通の型でなければなりません。r
定義されている std.traits.CommonType。 もしn
の長さがr
場合、r
変更されずに返されます。もしr
Unicode 文字を含む文字列である場合、padLeft
文字列の長さに関するDの規則に従う。 これは文字の数ではなく、 表記素の数でもない。代わりに、エンコーディング単位の数である。各表記素を エンコーディング単位の長さ1つ分として扱いたい場合は、std.uni.byGraphemeこの関数を呼び出す前に もしr
長さがある場合は、これはΟ(1) となります。それ以外の場合、これはΟ(r.length) となります。Parameters:R r
長さを持つ入力範囲、または前方一致する範囲 E e
要素で、パディングする size_t n
パディングする長さの Returns: 元の範囲の要素を含む範囲で、余分なパディングが追加されている xml-ph-0000@deepl.internal 関連項目:element要素元の範囲の要素を含む範囲で、余分なパディングが追加されている 関連項目: std.string.leftJustifierExamples:import std.algorithm.comparison : equal; assert([1, 2, 3, 4].padLeft(0, 6).equal([0, 0, 1, 2, 3, 4])); assert([1, 2, 3, 4].padLeft(0, 3).equal([1, 2, 3, 4])); assert("abc".padLeft('_', 6).equal("___abc"));
- auto
padRight
(R, E)(Rr
, Ee
, size_tn
)
if (isInputRange!R && !isInfinite!R && !is(CommonType!(ElementType!R, E) == void)); - 入力範囲の長さを拡張するには、
r
範囲の末尾を 要素で埋めることでe
。要素はe
範囲の要素型と共通の型でなければなりません。r
定義されている std.traits.CommonType。 もしn
の長さがr
場合は、その内容がr
返されます。結果として得られる範囲が提供する範囲のプリミティブは、それが提供するかどうかによって異なるr
それらを提供するかどうかによって異なります。back とpopBack という関数を除いて、 範囲の長さも必要となります。back とpopBackも同様です。Parameters:R r
長さを持つ入力範囲 E e
要素で範囲をパディングする size_t n
パディングする長さ Returns: 元の範囲の要素を含む範囲で、余分なパディングが追加されている xml-ph-0000@deepl.internal 関連項目:element要素元の範囲の要素を含む範囲に、余分なパディングを追加したもの 関連項目: std.string.rightJustifierExamples:import std.algorithm.comparison : equal; assert([1, 2, 3, 4].padRight(0, 6).equal([1, 2, 3, 4, 0, 0])); assert([1, 2, 3, 4].padRight(0, 4).equal([1, 2, 3, 4])); assert("abc".padRight('_', 6).equal("abc___"));
- enum auto
isSomeFiniteCharInputRange
(R); - これは、phobosでよく使用される、あらゆる種類の文字列パラメータを受け入れるためのイディオムを簡素化する。R という型は、例えば単純な文字列、連結文字列などであるstd.range.chain、 std.path.chainPathまたはその他の文字の範囲を入力として 使用できます。この制約では、有限長の文字列のみが許可される。 このテンプレートは次のものと同義である。
isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R)
See Also:to beだExamples:to beだimport std.path : chainPath; import std.range : chain; void someLibraryMethod(R)(R argument) if (isSomeFiniteCharInputRange!R) { // 実装の詳細については、引数の各文字を繰り返し処理する } someLibraryMethod("simple strings work"); someLibraryMethod(chain("chained", " ", "strings", " ", "work")); someLibraryMethod(chainPath("chained", "paths", "work")); // 文字の範囲を実装したカスタム構造体を使用することもできる
DEEPL APIにより翻訳、ところどころ修正。
このページの最新版(英語)
このページの原文(英語)
翻訳時のdmdのバージョン: 2.109.1
ドキュメントのdmdのバージョン: 2.109.1
翻訳日付 :
HTML生成日時:
編集者: dokutoku