Как объединить два std::vector
?Конкатенирование двух std :: векторов
ответ
Я бы использовать insert function, что-то вроде:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
vector1.insert(vector1.end(), vector2.begin(), vector2.end());
Я бы только добавил код, чтобы сначала получить количество элементов, каждый из которых удерживается в векторе, и установить vector1 как тот, который будет наибольшим. Если вы это сделаете, вы делаете много ненужного копирования. – 2008-10-14 16:11:42
У меня вопрос. Будет ли это работать, если vector1 и vector2 являются одинаковыми векторами? – 2011-07-17 09:36:28
Если вы связываете несколько векторов с одним, полезно ли сначала вызвать «резерв» в векторе назначения? – 2012-02-04 23:07:59
std::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
Или вы могли бы использовать:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
Эта модель является полезным, если два вектора не содержат точно такой же тип вещей, потому что вы можете использовать что-то вместо std :: back_inserter для преобразования из одного типа в другой.
Если вы используете C++ 11, и хотите, чтобы переместить элементы, а не просто копировать их, вы можете использовать зЬй :: move_iterator (http://en.cppreference.com/w/cpp/iterator/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;
}
Это не будет более эффективным для примера с Интс, так как перемещение их не более эффективны, чем их копирования, но для структуры данных с оптимизированными ходов, он может избежать копирования ненужного состояния:
#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 в конце.
Если вы заинтересованы в сильной гарантии исключения (когда копия конструктор может бросить исключение):
template<typename T>
inline void append_copy(std::vector<T>& v1, const std::vector<T>& 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
с сильной гарантией не может быть реализована в общем, если конструктор перемещения элемента вектора может бросить (который маловероятно, но все же).
С C++ 11, я предпочитаю следующее добавление вектора Ь к а:
std::move(b.begin(), b.end(), std::back_inserter(a));
когда a
и b
не перекрываются, и b
не будет больше использоваться.
Добавить этот в файл заголовка:
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);
г будет содержать [1,2,62]
Если то, что вы» re look for - это способ добавить вектор к другому после создания, vector::insert
- ваш лучший выбор, так как был дан ответ несколько раз, например:
vector<int> first = {13};
const vector<int> second = {42};
first.insert(first.end(), second.cbegin(), second.cend());
К сожалению, нет возможности построить const vector<int>
, как указано выше, и вы должны построить insert
.
Если то, что вы на самом деле ищете является контейнером для хранения конкатенации этих два vector<int>
с, может быть что-то лучше доступно для вас, если:
- Вашего
vector
содержит примитивы - Ваши содержащиеся примитивы имеют размер 32 бита или меньше
- Вы хотите
const
контейнер
Если все это верно, я бы предложил использовать basic_string
, который соответствует 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
Я предпочитаю тот, который уже упоминался:
a.insert(a.end(), b.begin(), b.end());
Но если вы используете C++ 11, есть еще один общий способ:
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());
}
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
Честно говоря, вы можете быстро объединить два вектора от копирования элементов из двух векторов в другой или просто только добавить один из двух векторы !. Это зависит от вашей цели.
Способ 1: Назначить новый вектор с его размером - это сумма двух исходных векторов.
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.
// 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());
Вы должны использовать vector::insert
v1.insert(v1.end(), v2.begin(), v2.end());
Вот общее решение цели с помощью C++ 11 перемещения семантики:
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
if (lhs.empty()) return rhs;
if (rhs.empty()) return lhs;
std::vector<T> 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 <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
lhs.insert(result.cend(), rhs.cbegin(), rhs.cend());
return std::move(lhs);
}
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
return std::move(rhs);
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& 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);
}
Обратите внимание, как это отличается от append
ИНГОВ к vector
.
- 1. XLST конкатенирование двух массивов
- 2. std :: bad_alloc при конкатенации двух векторов
- 3. конкатенирование (добавление) двух строк charcter
- 4. конкатенирование двух int в java
- 5. Показать карту двух векторов
- 6. Iterable объединение двух векторов
- 7. Лучший способ найти пересечение двух std :: векторов 3D-точек
- 8. есть ли std :: несоответствие для двух векторов неравного размера?
- 9. Добавление двух векторов вместе
- 10. Clojure - слияние двух векторов векторов разных размеров
- 11. Сравнить значения двух векторов
- 12. Сравнение двух векторов
- 13. Сравнение двух векторов (Java)
- 14. Сортировка двух векторов сразу?
- 15. Matlab, пересечение двух векторов
- 16. Сортировка двух векторов отдельно?
- 17. Соответствующие значения двух векторов
- 18. FDR сравнения двух векторов
- 19. Сравнение двух векторов
- 20. Построение двух отдельных векторов
- 21. Матричное умножение двух векторов
- 22. Объединение значений двух векторов разного размера
- 23. Слияние двух векторов STL с шаблоном чередования
- 24. C++: формирование цикла с использованием двух векторов
- 25. Смещение вычитания с учетом двух отсортированных векторов
- 26. C++ удалять повторяющиеся элементы из двух векторов
- 27. Std-вектор std-матриц (вектор векторов) в C++
- 28. Конкатенирование параллельных потоков
- 29. switch() на основе двух векторов
- 30. torch.Tensor манипуляции - Сравнение двух векторов
Ответы, приведенные, на самом деле не совпадают. Они добавляют копию. Может быть использование (для точки зрения эффективности) создания метода std :: vector concatenate, однако для этого потребуется некоторый сложный совместный подход к управлению узлами, и, вероятно, поэтому он не был выполнен. – FauChristian 2017-02-15 19:07:59
@FauChristian: Нет, с точки зрения эффективности не может быть пользы. Векторная память должна быть непрерывной, поэтому предлагаемое вами невозможно. Если вам нужен «некоторый сложный совместный доступ к управлению узлами», и если бы вы таким образом изменили векторный класс, вы попали бы в deque. Даже тогда очень трудно повторно использовать память, как предполагалось, хотя она начнет быть немного более выполнимой. Я не думаю, что это в настоящее время реализовано. Главное, что при таком совместном использовании узлов управления (deque) конечный узел может быть частично пустым. – Cookie 2017-05-16 10:00:41
@lecaruyer Вы понимаете, что вы просто отметили вопрос, который был задан два года назад, как дубликат. – eshirima 2017-08-03 12:47:50