Объединение двух std :: vectors
Как объединить два элемента std::vector
?
9X_concatenation
- @FauChristian: Нет, с точки зрения эффективности это может быть бесполезно. Векторная память должна быть непрерывной, поэтому то, что вам предлагают, ...
Ответ #1
Ответ на вопрос: Объединение двух std :: vectors
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
9X_cpp
- Если у вас есть объединение нескольких векторов в ...
Ответ #2
Ответ на вопрос: Объединение двух std :: vectors
Если вы используете C++ 11 и хотите переместить 9X_stdvector элементы, а не просто копировать их, вы 9X_cpp можете использовать std::move_iterator
вместе со вставкой 9X_cpp (или копией):
#include
#include
#include
int main(int argc, char** argv) {
std::vector dest{1,2,3,4,5};
std::vector 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(std::cout, "\n")
);
return 0;
}
Это не будет более эффективным 9X_c++ для примера с целыми числами, поскольку 9X_concat их перемещение не более эффективно, чем 9X_cpp их копирование, но для структуры данных 9X_cpp с оптимизированными перемещениями это может 9X_cxx избежать копирования ненужного состояния:
#include
#include
#include
int main(int argc, char** argv) {
std::vector> dest{{1,2,3,4,5}, {3,4}};
std::vector> 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;
}
После 9X_concatenate перемещения элемент src остается в неопределенном, но 9X_vector безопасном для уничтожения состоянии, а 9X_concat его прежние элементы были перенесены непосредственно 9X_cpp в новый элемент dest в конце.
- @kshenoy, `insert` может выделить ...
Ответ #3
Ответ на вопрос: Объединение двух std :: vectors
Я бы использовал insert function, что-то вроде:
vector a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
9X_concatenation
Ответ #4
Ответ на вопрос: Объединение двух std :: vectors
Или вы можете использовать:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
Этот шаблон полезен, если 9X_concat два вектора не содержат в точности один 9X_concatenation и тот же тип объектов, потому что вы можете 9X_cpp использовать что-то вместо std :: back_inserter 9X_stl для преобразования из одного типа в другой.
- метод копирования - не самый лучший способ. Он будет вызывать push_back несколько раз, ...
Ответ #5
Ответ на вопрос: Объединение двух std :: vectors
В C++ 11 я бы предпочел добавить вектор 9X_cxx b к a следующим образом:
std::move(b.begin(), b.end(), std::back_inserter(a));
когда a
и b
не перекрываются, и 9X_cxx b
больше не будет использоваться.
Это std::move
из 9X_stl-containers
, а не обычный std::move
из
.
- Неопределенное поведение, если a на самом деле равно b (что нормал ...
Ответ #6
Ответ на вопрос: Объединение двух std :: vectors
std::vector
first; std::vector second; first.insert(first.end(), second.begin(), second.end()); 9X_concat
Ответ #7
Ответ на вопрос: Объединение двух std :: vectors
Я предпочитаю тот, который уже упоминался:
a.insert(a.end(), b.begin(), b.end());
Но 9X_vector если вы используете C++ 11, есть еще один 9X_concat общий способ:
a.insert(std::end(a), std::begin(b), std::end(b));
Кроме того, это не является 9X_concatenation частью вопроса, но для повышения производительности 9X_vectors рекомендуется использовать reserve
перед добавлением. И 9X_concatenation если вы объединяете вектор с самим собой, без 9X_concat его резервирования не удается, поэтому вам 9X_stdvector всегда следует reserve
.
Итак, в основном то, что 9X_stdvector вам нужно:
template
void Append(std::vector& a, const std::vector& b)
{
a.reserve(a.size() + b.size());
a.insert(a.end(), b.begin(), b.end());
}
- лучше не использовать резерв, так как это может повлечь за собой огромные накладные расходы. Посмотрите здесь: https://s ...
Ответ #8
Ответ на вопрос: Объединение двух std :: vectors
- Я предполагаю, что это будет подходящий ответ примерно в 2023 году. ...
Ответ #9
Ответ на вопрос: Объединение двух std :: vectors
Общее повышение производительности для конкатенации - это проверка размера 9X_c++ векторов. И объедините / вставьте меньший 9X_stl-containers с большим.
//vector v1,v2;
if(v1.size()>v2.size()) {
v1.insert(v1.end(),v2.begin(),v2.end());
} else {
v2.insert(v2.end(),v1.begin(),v1.end());
}
- Вы также можете использовать быструю замену. @DavidStone Я отредактировал его, чтобы можно было изменить порядок ко ...
Ответ #10
Ответ на вопрос: Объединение двух std :: vectors
Если вы хотите иметь возможность кратко 9X_concatenate объединять векторы, вы можете перегрузить 9X_concatenate оператор +=
.
template
std::vector& operator +=(std::vector& vector1, const std::vector& vector2) {
vector1.insert(vector1.end(), vector2.begin(), vector2.end());
return vector1;
}
Тогда вы можете назвать это так:
vector1 += vector2;
Ответ #11
Ответ на вопрос: Объединение двух std :: vectors
Существует алгоритм std::merge
из C++ 17, который очень 9X_c++ легко использовать при сортировке входных 9X_stl векторов
Ниже приведен пример:
#include
#include
#include
int main()
{
//DATA
std::vector v1{2,4,6,8};
std::vector v2{12,14,16,18};
//MERGE
std::vector dst;
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));
//PRINT
for(auto item:dst)
std::cout<
- Я не думаю, что его проще использовать, чем `std :: vector :: insert`, но он р ...
Ответ #12
Ответ на вопрос: Объединение двух std :: vectors
Если вас интересует строгая гарантия исключения 9X_stdvector (когда конструктор копирования может вызвать 9X_cpp исключение):
template
inline void append_copy(std::vector& v1, const std::vector& v2)
{
const auto orig_v1_size = v1.size();
v1.reserve(orig_v1_size + v2.size());
try
{
v1.insert(v1.end(), v2.begin(), v2.end());
}
catch(...)
{
v1.erase(v1.begin() + orig_v1_size, v1.end());
throw;
}
}
Подобный append_move
с сильной гарантией 9X_stl не может быть реализован в целом, если конструктор 9X_concat перемещения векторного элемента может бросать 9X_vector (что маловероятно, но все же).
Ответ #13
Ответ на вопрос: Объединение двух std :: vectors
- Разве это не то же самое с ответом, данным ...
Ответ #14
Ответ на вопрос: Объединение двух std :: vectors
Если ваша цель - просто перебрать диапазон 9X_concatenation значений только для чтения, альтернативой 9X_stl-containers является обернуть оба вектора вокруг прокси 9X_stdvector (O (1)) вместо их копирования (O (n)), чтобы 9X_concatenate они сразу же воспринимаются как единый, непрерывный.
std::vector A{ 1, 2, 3, 4, 5};
std::vector B{ 10, 20, 30 };
VecProxy 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
Обратитесь 9X_vectors к https://stackoverflow.com/a/55838758/2379625 для получения дополнительных сведений, включая 9X_concatenate реализацию VecProxy, а также плюсы и минусы.
Ответ #15
Ответ на вопрос: Объединение двух std :: vectors
Добавьте это в свой заголовочный файл:
template vector concat(vector &a, vector &b) {
vector ret = vector();
copy(a.begin(), a.end(), back_inserter(ret));
copy(b.begin(), b.end(), back_inserter(ret));
return ret;
}
и 9X_concatenate используйте его так:
vector a = vector();
vector b = vector();
a.push_back(1);
a.push_back(2);
b.push_back(62);
vector r = concat(a, b);
r будет содержать [1,2,62]
Ответ #16
Ответ на вопрос: Объединение двух std :: vectors
Используя C++20, вы можете избавиться от 9X_stdvector begin() и end() с диапазонами.
#include
std::ranges::copy(vec2, std::back_inserter(vec1));
или если вы 9X_concatenate хотите переместить элементы:
std::ranges::move(vec2, std::back_inserter(vec1));
Ответ #17
Ответ на вопрос: Объединение двух std :: vectors
Вот решение общего назначения, использующее 9X_vectors семантику перемещения C++ 11:
template
std::vector concat(const std::vector& lhs, const std::vector& rhs)
{
if (lhs.empty()) return rhs;
if (rhs.empty()) return lhs;
std::vector result {};
result.reserve(lhs.size() + rhs.size());
result.insert(result.cend(), lhs.cbegin(), lhs.cend());
result.insert(result.cend(), rhs.cbegin(), rhs.cend());
return result;
}
template
std::vector concat(std::vector&& lhs, const std::vector& rhs)
{
lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
return std::move(lhs);
}
template
std::vector concat(const std::vector& lhs, std::vector&& rhs)
{
rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
return std::move(rhs);
}
template
std::vector concat(std::vector&& lhs, std::vector&& rhs)
{
if (lhs.empty()) return std::move(rhs);
lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
return std::move(lhs);
}
Обратите внимание, чем 9X_vector это отличается от append
от vector
.
Ответ #18
Ответ на вопрос: Объединение двух std :: vectors
Вы можете подготовить свой собственный шаблон 9X_concatenate для оператора +:
template
inline T operator+(const T & a, const T & b)
{
T res = a;
res.insert(res.end(), b.begin(), b.end());
return res;
}
Следующее - просто используйте 9X_stdvector +:
vector a{1, 2, 3, 4};
vector b{5, 6, 7, 8};
for (auto x: a + b)
cout << x << " ";
cout << endl;
Этот пример дает результат:
1 2 3 4 5 6 7 8
- Использование`T operator + (const T & a, const T & b) `опасно, лучше использовать` vector <t> op ...
Ответ #19
Ответ на вопрос: Объединение двух std :: vectors
vector
v1 = {1, 2, 3, 4, 5}; vector v2 = {11, 12, 13, 14, 15}; copy(v2.begin(), v2.end(), back_inserter(v1)); 9X_vectors
- Хотя этот фрагмент кода может решить проблему, он не объясняет, почему и как он отвечает на вопрос. Пожалуйста [включите объяснение вашего кода] (// meta.stackexchange.com/q/114762/269535), так как это действительно помогает улучшить качеств ...
Ответ #20
Ответ на вопрос: Объединение двух std :: vectors
Я реализовал эту функцию, которая объединяет 9X_vectors любое количество контейнеров, перемещаясь 9X_concatenation из rvalue-ссылок и копируя в противном случае
namespace internal {
// Implementation detail of Concatenate, appends to a pre-reserved vector, copying or moving if
// appropriate
template
void AppendNoReserve(Target* target, Head&& head, Tail&&... tail) {
// Currently, require each homogenous inputs. If there is demand, we could probably implement a
// version that outputs a vector whose value_type is the common_type of all the containers
// passed to it, and call it ConvertingConcatenate.
static_assert(
std::is_same_v<
typename std::decay_t::value_type,
typename std::decay_t::value_type>,
"Concatenate requires each container passed to it to have the same value_type");
if constexpr (std::is_lvalue_reference_v) {
std::copy(head.begin(), head.end(), std::back_inserter(*target));
} else {
std::move(head.begin(), head.end(), std::back_inserter(*target));
}
if constexpr (sizeof...(Tail) > 0) {
AppendNoReserve(target, std::forward(tail)...);
}
}
template
size_t TotalSize(const Head& head, const Tail&... tail) {
if constexpr (sizeof...(Tail) > 0) {
return head.size() + TotalSize(tail...);
} else {
return head.size();
}
}
} // namespace internal
/// Concatenate the provided containers into a single vector. Moves from rvalue references, copies
/// otherwise.
template
auto Concatenate(Head&& head, Tail&&... tail) {
size_t totalSize = internal::TotalSize(head, tail...);
std::vector::value_type> result;
result.reserve(totalSize);
internal::AppendNoReserve(&result, std::forward(head), std::forward(tail)...);
return result;
}
Ответ #21
Ответ на вопрос: Объединение двух std :: vectors
Это решение может быть немного сложным, но 9X_vector boost-range
может предложить и другие приятные вещи.
#include
#include
#include
int main(int, char**) {
std::vector a = { 1,2,3 };
std::vector b = { 4,5,6 };
boost::copy(b, std::back_inserter(a));
for (auto& iter : a) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
Часто 9X_stl-containers намерение состоит в том, чтобы объединить 9X_concatenation vector a
и b
, просто перебирая его, выполняя 9X_vector некоторую операцию. В этом случае есть нелепая 9X_concatenation простая функция join
.
#include
#include
#include
#include
int main(int, char**) {
std::vector a = { 1,2,3 };
std::vector b = { 4,5,6 };
std::vector c = { 7,8,9 };
// Just creates an iterator
for (auto& iter : boost::join(a, boost::join(b, c))) {
std::cout << iter << " ";
}
std::cout << "\n";
// Can also be used to create a copy
std::vector d;
boost::copy(boost::join(a, boost::join(b, c)), std::back_inserter(d));
for (auto& iter : d) {
std::cout << iter << " ";
}
return EXIT_SUCCESS;
}
Для больших векторов это 9X_vectors может быть преимуществом, поскольку отсутствует 9X_stdvector копирование. Его также можно использовать 9X_vector для простого копирования обобщений на более 9X_concatenation чем один контейнер.
По какой-то причине нет 9X_vector ничего похожего на boost::join(a,b,c)
, что могло бы быть разумным.
Ответ #22
Ответ на вопрос: Объединение двух std :: vectors
Для контейнеров, предлагающих push_back
(строка, вектор, двухсторонняя 9X_stl-containers очередь, ...):
std::copy(std::begin(input), std::end(input), std::back_inserter(output))
и
для контейнеров, предлагающих 9X_concatenation insert
(карты, наборы):
std::copy(std::begin(input), std::end(input), std::inserter(output, output.end()))
-
4
-
6
-
9
-
4
-
6
-
3
-
3
-
7
-
5
-
7
-
5
-
5
-
1
-
8
-
6
-
5
-
3
-
9
-
4
-
5
-
25
-
3
-
11
-
4
-
4
-
2
-
4
-
12
-
9
-
4
-
9
-
13
-
5
-
10
-
12
-
14
-
6
-
8
-
4
-
8
-
14
-
5
-
7
-
12
-
8
-
18
-
7
-
10
-
11
-
3