私が持っていると仮定しstd::vector
(せのはそれを呼び出すmyVec
サイズの)N
。要素XからYまでのコピーで構成される新しいベクトルを作成する最も簡単な方法は何ですか(0 <= X <= Y <= N-1)。たとえば、sizeのベクトルをmyVec [100000]
通過myVec [100999]
します150000
。
これをベクトルで効率的に実行できない場合、代わりに使用する必要がある別のSTLデータ型はありますか?
私が持っていると仮定しstd::vector
(せのはそれを呼び出すmyVec
サイズの)N
。要素XからYまでのコピーで構成される新しいベクトルを作成する最も簡単な方法は何ですか(0 <= X <= Y <= N-1)。たとえば、sizeのベクトルをmyVec [100000]
通過myVec [100999]
します150000
。
これをベクトルで効率的に実行できない場合、代わりに使用する必要がある別のSTLデータ型はありますか?
回答:
vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
vector<T> newVec(first, last);
新しいベクトルを作成するのはO(N)演算ですが、実際にはもっと良い方法はありません。
O(Y-X)
、と言いO(Z) where Z=Y-X
ます。
vector<T> newVec(myVec.begin() + 100000, myVec.begin() + 101000);
ですか?
ベクトルコンストラクタを使用するだけです。
std::vector<int> data();
// Load Z elements into data so that Z > Y > X
std::vector<int> sub(&data[100000],&data[101000]);
operator[]
参照を返すことを覚えておいてください。アクセス違反になるのは、参照を読み書きしたときだけです。どちらも実行せず、代わりにアドレスを取得しているため、UBを呼び出していません。
std::vector<T>(input_iterator, input_iterator)
、あなたのケースfoo = std::vector<T>(myVec.begin () + 100000, myVec.begin () + 150000);
では、例えばここを参照してください
最近では、span
s を使用しています。だからあなたは書くでしょう:
#include <gsl/span>
...
auto start_pos = 100000;
auto length = 1000;
auto span_of_myvec = gsl::make_span(myvec);
auto my_subspan = span_of_myvec.subspan(start_pos, length);
と同じタイプの1000要素のスパンを取得しますmyvec
。またはより簡潔な形式:
auto my_subspan = gsl::make_span(myvec).subspan(1000000, 1000);
(しかし、各数値引数の意味が完全に明確ではないため、これはあまり好きではありません。また、lengthとstart_posが同じ桁数であると、さらに悪くなります。)
とにかく、これはコピーではなく、ベクター内のデータの単なるビューであることを忘れないでください。注意してください。実際のコピーが必要な場合は、次のようにすることができます。
std::vector<T> new_vec(my_subspan.cbegin(), my_subspan.cend());
ノート:
gsl
ガイドラインサポートライブラリの略です。の詳細についてはgsl
、http : //www.modernescpp.com/index.php/c-core-guideline-the-guidelines-support-libraryを参照してください。gsl
、https://github.com/Microsoft/GSLを参照してください。span
。std::span
と#include <span>
ではなく、を使用します#include <gsl/span>
。std::vector
には膨大な数のコンストラクタがあり、使用するつもりのないコンストラクタに分類するのは非常に簡単なので、注意してください。cbegin
しcend
ます;)std::cbegin
など。
両方を変更しない場合(アイテムの追加/削除なし-スレッドの問題に注意を払っている限り、既存のものの変更は問題ありません)、単純にdata.begin() + 100000
andを渡しdata.begin() + 101000
、それらがbegin()
とend()
より小さいベクトルのふりをすることができます。
または、ベクトルストレージは連続していることが保証されているので、1000アイテムの配列を単純に渡すことができます。
T *arrayOfT = &data[0] + 100000;
size_t arrayOfTLength = 1000;
これらの手法はどちらも一定の時間がかかりますが、データの長さが増加しないことを要求し、再割り当てをトリガーします。
この議論はかなり古いですが、最も単純なものはリスト初期化でまだ言及されていません:
vector<int> subvector = {big_vector.begin() + 3, big_vector.end() - 2};
c ++ 11以上が必要です。
使用例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
vector<int> big_vector = {5,12,4,6,7,8,9,9,31,1,1,5,76,78,8};
vector<int> subvector = {big_vector.begin() + 3, big_vector.end() - 2};
cout << "Big vector: ";
for_each(big_vector.begin(), big_vector.end(),[](int number){cout << number << ";";});
cout << endl << "Subvector: ";
for_each(subvector.begin(), subvector.end(),[](int number){cout << number << ";";});
cout << endl;
}
結果:
Big vector: 5;12;4;6;7;8;9;9;31;1;1;5;76;78;8;
Subvector: 6;7;8;9;9;31;1;1;5;76;
あなたは型std::vector<...> myVec
が何であるかについては触れませんでしたが、ポインタを含まない単純な型または構造体/クラスであり、最高の効率が必要な場合は、直接メモリコピーを実行できます(これは、他の回答が提供されています)。ここのための一般的な例であるstd::vector<type> myVec
ところtype
、この場合には、ありますint
:
typedef int type; //choose your custom type/struct/class
int iFirst = 100000; //first index to copy
int iLast = 101000; //last index + 1
int iLen = iLast - iFirst;
std::vector<type> newVec;
newVec.resize(iLen); //pre-allocate the space needed to write the data directly
memcpy(&newVec[0], &myVec[iFirst], iLen*sizeof(type)); //write directly to destination buffer from source buffer
std::vector(myVec.begin () + 100000, myVec.begin () + 150000);
すると、この長いバージョンがまったく同じアセンブリに生成されないのではないでしょうか。
std::vector<>(iter, iter)
れmemmove()
ます(コンストラクターが自明の場合、自明の適切な定義)。
memcpy
。やるstd::copy
範囲(2回の反復子)、およびコンパイラを受け入れ、std.libraryを呼び出すために共謀しますまたはコンストラクタmemcpy
適切な場合に。
あなたはただ使うことができます insert
vector<type> myVec { n_elements };
vector<type> newVec;
newVec.insert(newVec.begin(), myVec.begin() + X, myVec.begin() + Y);
Mがサブベクトルのサイズである場合、STLコピーをO(M)パフォーマンスで使用できます。
newvec.reserve(10100 - 10000);
。ITは間違いなくオプションであり、技術的には機能します。しかし、あなたが推薦する2つのうちのどれですか?
線形時間ではないコレクションを投影する唯一の方法は、遅延して行うことです。この場合、結果の「ベクトル」は、実際には元のコレクションに委譲するサブタイプになります。たとえば、ScalaのList#subseq
メソッドは、一定の時間でサブシーケンスを作成します。ただし、これが機能するのは、コレクションが不変で、基になる言語がスポーツガベージコレクションである場合のみです。
これを他の人のためだけに遅らせて投稿します。最初のコーダーは今では完成しているでしょう。単純なデータ型の場合、コピーは必要ありません。古き良きCコードメソッドに戻してください。
std::vector <int> myVec;
int *p;
// Add some data here and set start, then
p=myVec.data()+start;
次に、ポインターpとlenをサブベクトルが必要なものに渡します。
notelenである必要があります!! len < myVec.size()-start
多分array_view / span GSLライブラリが適切なオプションです。
これも単一ファイルの実装です:array_view。
あるベクトルから別のベクトルに要素を簡単にコピーする
この例では、ペアのベクトルを使用して理解しやすくしています
`
vector<pair<int, int> > v(n);
//we want half of elements in vector a and another half in vector b
vector<pair<lli, lli> > a(v.begin(),v.begin()+n/2);
vector<pair<lli, lli> > b(v.begin()+n/2, v.end());
//if v = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
//then a = [(1, 2), (2, 3)]
//and b = [(3, 4), (4, 5), (5, 6)]
//if v = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7)]
//then a = [(1, 2), (2, 3), (3, 4)]
//and b = [(4, 5), (5, 6), (6, 7)]
'
ご覧のように、要素をあるベクトルから別のベクトルに簡単にコピーできます。たとえば、インデックス10から16に要素をコピーする場合は、
vector<pair<int, int> > a(v.begin()+10, v.begin+16);
インデックス10の要素を末尾からインデックスにしたい場合は、その場合
vector<pair<int, int> > a(v.begin()+10, v.end()-5);
これが役立つことを願って、最後のケースで覚えてください v.end()-5 > v.begin()+10
さらに別のオプション:コンストラクターを使用できないa thrust::device_vector
との間を移動する場合などに便利ですthrust::host_vector
。
std::vector<T> newVector;
newVector.reserve(1000);
std::copy_n(&vec[100000], 1000, std::back_inserter(newVector));
複雑さO(N)も必要
これをトップアンワーコードと組み合わせることができます
vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
std::copy(first, last, std::back_inserter(newVector));