2 つの s を連結するにはどうすればよいstd::vector
ですか?
26 に答える
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
C++11 を使用していて、要素を単にコピーするのではなく移動したい場合はstd::move_iterator
、挿入 (またはコピー) と共に使用できます。
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<int> dest{1,2,3,4,5};
std::vector<int> src{6,7,8,9,10};
// Move elements from src to dest.
// src is left in undefined but safe-to-destruct state.
dest.insert(
dest.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end())
);
// Print out concatenated vector.
std::copy(
dest.begin(),
dest.end(),
std::ostream_iterator<int>(std::cout, "\n")
);
return 0;
}
これは、int を使用した例では効率的ではありません。移動はコピーよりも効率的ではないためです。ただし、移動が最適化されたデータ構造では、不要な状態のコピーを回避できます。
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
std::vector<std::vector<int>> src{{6,7,8,9,10}};
// Move elements from src to dest.
// src is left in undefined but safe-to-destruct state.
dest.insert(
dest.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end())
);
return 0;
}
移動後、src の要素は未定義ですが安全に破壊できる状態のままになり、最後に以前の要素が dest の新しい要素に直接転送されました。
次のような挿入関数を使用します。
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
または、次を使用できます。
std::copy(source.begin(), source.end(), std::back_inserter(destination));
このパターンは、2つのベクトルにまったく同じタイプのものが含まれていない場合に役立ちます。これはstd::back_inserter
、あるタイプから別のタイプに変換する代わりに、何かを使用できるためです。
std::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
私はすでに言及されているものを好みます:
a.insert(a.end(), b.begin(), b.end());
しかし、C++11 を使用する場合は、もう 1 つの一般的な方法があります。
a.insert(std::end(a), std::begin(b), std::end(b));
また、質問の一部ではありませんが、reserve
パフォーマンスを向上させるために追加する前に使用することをお勧めします。また、ベクトルをそれ自体と連結している場合、予約せずに失敗するため、常にreserve
.
基本的に必要なもの:
template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
a.reserve(a.size() + b.size());
a.insert(a.end(), b.begin(), b.end());
}
ベクトルを簡潔に連結できるようにしたい場合は、+=
演算子をオーバーロードできます。
template <typename T>
std::vector<T>& operator +=(std::vector<T>& vector1, const std::vector<T>& vector2) {
vector1.insert(vector1.end(), vector2.begin(), vector2.end());
return vector1;
}
次に、次のように呼び出すことができます。
vector1 += vector2;
vector::insertを使用する必要があります
v1.insert(v1.end(), v2.begin(), v2.end());
読み取り専用の目的で値の範囲を単純に反復することが目的の場合、代わりに、両方のベクトルをコピー (O(n)) する代わりに、プロキシ (O(1)) でラップすることで、すぐに表示されるようにします。単一の連続したものとして。
std::vector<int> A{ 1, 2, 3, 4, 5};
std::vector<int> B{ 10, 20, 30 };
VecProxy<int> AB(A, B); // ----> O(1)!
for (size_t i = 0; i < AB.size(); i++)
std::cout << AB[i] << " "; // ----> 1 2 3 4 5 10 20 30
「VecProxy」の実装や長所と短所などの詳細については、https: //stackoverflow.com/a/55838758/2379625 を参照してください。
これをヘッダー ファイルに追加します。
template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
vector<T> ret = vector<T>();
copy(a.begin(), a.end(), back_inserter(ret));
copy(b.begin(), b.end(), back_inserter(ret));
return ret;
}
次のように使用します。
vector<int> a = vector<int>();
vector<int> b = vector<int>();
a.push_back(1);
a.push_back(2);
b.push_back(62);
vector<int> r = concat(a, b);
r には [1,2,62] が含まれます
+ 演算子用に独自のテンプレートを用意できます。
template <typename T>
inline T operator+(const T & a, const T & b)
{
T res = a;
res.insert(res.end(), b.begin(), b.end());
return res;
}
次のこと-+を使用するだけです:
vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
cout << x << " ";
cout << endl;
この例では、次の出力が得られます。
1 2 3 4 5 6 7 8
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
探しているものが、作成後にベクターを別のベクターに追加する方法である場合は、次のようにvector::insert
何度か回答されているように、最善の策です。
vector<int> first = {13};
const vector<int> second = {42};
first.insert(first.end(), second.cbegin(), second.cend());
悲しいことに、 a を構築する方法はconst vector<int>
ありません。上記のように、構築してからinsert
.
実際に探しているのがこれら 2 つvector<int>
の s の連結を保持するコンテナーである場合は、次の場合により適切なものが利用できる可能性があります。
- プリミティブ
vector
が含まれています - 含まれているプリミティブのサイズは 32 ビット以下です
const
コンテナが欲しい
上記がすべて当てはまる場合は、に含まれるプリミティブのサイズに一致するbasic_string
whoを使用することをお勧めします。これらのサイズが一貫していることを検証するには、コードに を含める必要があります。char_type
vector
static_assert
static_assert(sizeof(char32_t) == sizeof(int));
これを真にすると、次のことができます。
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
string
との違いの詳細については、こちらを参照しvector
てください: https://stackoverflow.com/a/35558008/2642059
このコードの実際の例については、http: //ideone.com/7Iww3Iを参照してください。
正直なところ、2 つのベクトルの要素を別のベクトルにコピーするか、2 つのベクトルの 1 つだけを追加することで、2 つのベクトルを高速に連結できます。それはあなたの目的次第です。
方法 1:サイズが 2 つの元のベクトルのサイズの合計である新しいベクトルを割り当てます。
vector<int> concat_vector = vector<int>();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector
方法 2:ベクトル B の要素を追加/挿入して、ベクトル A を追加します。
// Loop for insert elements of vector_B into vector_A with insert()
function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());