web-dev-qa-db-ja.com

ベクトルからサブベクトルを抽出する最良の方法は?

サイズがmyVecstd::vectorNと呼びましょう)があるとします。 XからYまでの要素のコピーからなる新しいベクトルを作る最も簡単な方法は何ですか?0 <= X <= Y <= N-1?たとえば、サイズがmyVec [100000]のベクトルのmyVec [100999]から150000まで。

ベクトルでこれを効率的に行うことができない場合は、代わりに使用すべき別のSTLデータ型がありますか?

247
An̲̳̳drew
vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
vector<T> newVec(first, last);

新しいベクトルを構築するのはO(N)操作ですが、それ以上良い方法はありません。

310
Greg Rogers

ベクトルコンストラクタを使うだけです。

std::vector<int>   data();
// Load Z elements into data so that Z > Y > X

std::vector<int>   sub(&data[100000],&data[101000]);
77
Martin York

std::vector(input_iterator, input_iterator)、あなたの場合はfoo = std::vector(myVec.begin () + 100000, myVec.begin () + 150000);、例えば参照してください ここ

24
Anteru

最近はspansを使っています。だからあなたは書くだろう:

#include <gsl/span>

...
auto start_pos = 100000;
auto length = 1000;
auto my_subspan = gsl::make_span(myvec).subspan(start_pos, length);

myvecと同じ型の1000個の要素からなるスパンを取得します。さて、これはコピーではなく、ベクトル内のデータの単なる表示なので、注意してください。実際のコピーが必要な場合は、次のようにします。

std::vector<T> new_vec(my_subspan.cbegin(), my_subspan.cend());

ノート:

11
einpoklum

両方とも修正されないのであれば(スレッドの問題に注意している限り、既存のものを修正することはできません)、単にdata.begin() + 100000data.begin() + 101000を迂回して、それらがbegin()end()のふりをすることができます。小さいベクトル.

あるいは、ベクトルストレージは連続していることが保証されているので、1000項目の配列を単純に渡すことができます。

T *arrayOfT = &data[0] + 100000;
size_t arrayOfTLength = 1000;

これらの手法はどちらも一定の時間がかかりますが、データの長さが増えずに再割り当てが行われることを必要とします。

10
Eclipse

std::vector<...> myVecの型については触れていませんが、ポインタを含まない単純型または構造体/クラスで、最も効率的なものが必要な場合は、直接メモリコピーを実行できます(これより速いでしょう)。提供された他の答え)。これはstd::vector<type> myVecの一般的な例です。この場合のtypeintです。

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
6
MasterHD

Mがサブベクトルのサイズである場合、O(M) performanceで STL copy を使用できます。

3
Yuval F

OK。これはかなり古い議論です。しかし、私はちょうど良いものを見つけました

slice_array - これは速い方法でしょうか。私はそれをテストしていません。

1
umayfindurself

線形時間ではないコレクションを射影する唯一の方法は、結果として得られる「ベクトル」が実際には元のコレクションに委譲されているサブタイプであるため、遅延して実行することです。たとえば、ScalaのList#subseqメソッドは一定時間でサブシーケンスを作成します。ただし、これはコレクションが不変であり、基になる言語がガベージコレクションを使用している場合にのみ機能します。

1
Daniel Spiewak

さらに別のオプション:thrust::device_vectorthrust::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));
0
JHBonarius

多分GSLライブラリの array_view/span が良い選択肢です。

これも単一ファイルの実装です: array_view

0
myd7349

insertを使うことができます

vector<type> myVec { n_elements };

vector<type> newVec;

newVec.insert(newVec.begin(), myVec.begin() + X, myVec.begin() + Y);

あるベクトルから別のベクトルに要素を簡単にコピーする
この例では、わかりやすくするためにペアのベクトルを使用しています
`

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を覚えていてください

0
Jishu Dohare

他人のためだけにこれを遅く投稿する..私は最初のコーダーが今で終わったと思います。単純なデータ型の場合、コピーは不要です。古き良き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

0
mrrgu