Объединение двух std :: векторов

Как объединить два std::vector s?

 vector1.insert( vector1.end(), vector2.begin(), vector2.end() ); 

Если вы используете C ++ 11 и хотите переместить элементы, а не просто их копировать, вы можете использовать std :: move_iterator ( http://en.cppreference.com/w/cpp/iterator/move_iterator ) вместе со вставкой (или копию):

 #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; } 

Это не будет более эффективным для примера с ints, так как перемещение их неэффективно, чем их копирование, но для структуры данных с оптимизированными ходами она может избежать копирования ненужного состояния:

 #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; } 

После перемещения элемент src остается в неопределенном, но безопасном для разрушения состоянии, и его прежние элементы были переданы непосредственно в новый элемент dest в конце.

Я бы использовал функцию вставки , например:

 vector a, b; //fill with data b.insert(b.end(), a.begin(), a.end()); 

Или вы можете использовать:

 std::copy(source.begin(), source.end(), std::back_inserter(destination)); 

Этот шаблон полезен, если два вектора не содержат точно такого же типа, потому что вы можете использовать что-то вместо std :: back_inserter для преобразования из одного типа в другой.

С C ++ 11 я предпочел бы добавить вектор b в a:

 std::move(b.begin(), b.end(), std::back_inserter(a)); 

когда a и b не перекрываются, и b больше не будет использоваться.

 std::vector first; std::vector second; first.insert(first.end(), second.begin(), second.end()); 

Я предпочитаю тот, который уже упоминался:

 a.insert(a.end(), b.begin(), b.end()); 

Но если вы используете C ++ 11, существует еще один общий способ:

 a.insert(std::end(a), std::begin(b), std::end(b)); 

Кроме того, это не часть вопроса, но рекомендуется использовать reserve перед добавлением для повышения производительности. И если вы конкатенируете вектор с собой, не оставляя его в силе, вы всегда должны его reserve .


Итак, в основном то, что вам нужно:

 template  void Append(std::vector& a, const std::vector& b) { a.reserve(a.size() + b.size()); a.insert(a.end(), b.begin(), b.end()); } 

Вы должны использовать вектор :: insert

 v1.insert(v1.end(), v2.begin(), v2.end()); 

Если вы заинтересованы в надежной гарантии исключения (когда конструктор копирования может вызвать исключение):

 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 с сильной гарантией не может быть реализован вообще, если конструктор перемещения векторного элемента может бросать (что маловероятно, но все же).

С диапазоном v3 у вас может быть ленивая конкатенация:

 ranges::view::concat(v1, v2) 

Демо .

 vector v1 = {1, 2, 3, 4, 5}; vector v2 = {11, 12, 13, 14, 15}; copy(v2.begin(), v2.end(), back_inserter(v1)); 

Добавьте этот файл в файл заголовка:

 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; } 

и использовать его таким образом:

 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]

Вот общее решение с использованием семантики перемещения 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); } 

Обратите внимание, что это отличается от append к vector .

Общее повышение производительности для конкатенации – проверка размера векторов. И объедините / вставьте меньший с большим.

 //vector v1,v2; if(v1.size()>v2.size()){ v1.insert(v1.end(),v2.begin(),v2.end()); }else{ v1.insert(v2.end(),v1.begin(),v1.end()); } 

Вы можете подготовить свой собственный шаблон для оператора +:

 template  inline T operator+(const T & a, const T & b) { T res = a; res.insert(res.end(), b.begin(), b.end()); return res; } 

Следующее – просто используйте +:

 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

Если то, что вы ищете, это способ добавить вектор к другому после создания, vector::insert – ваш лучший выбор, как было несколько раз ответили:

 vector first = {13}; const vector second = {42}; first.insert(first.end(), second.cbegin(), second.cend()); 

К сожалению, нет никакого способа построить const vector , как указано выше, вы должны построить и insert .


Если то, что вы действительно ищете, является контейнером для хранения конкатенации этих двух vector s, может быть что-то более доступное для вас, если:

  1. Ваш vector содержит примитивы
  2. Ваши содержащиеся примитивы имеют размер 32-бит или меньше
  3. Вы хотите, чтобы контейнер 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

Честно говоря, вы могли бы быстро объединить два вектора путем копирования элементов из двух векторов в другой или просто добавить один из двух векторов !. Это зависит от вашей цели.

Способ 1. Назначение нового вектора с его размером представляет собой сумму двух исходных векторов.

 vector concat_vector = vector(); concat_vector.setcapacity(vector_A.size() + vector_B.size()); // Loop for copy elements in two vectors into concat_vector 

Способ 2: добавить вектор A путем добавления / вставки элементов вектора 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()); 
  • Альтернативные, переплетенные или чередующиеся два вектора
  • Вычисление двумерного векторного изображения
  • Почему я не могу создать вектор lambdas (одного типа) в C ++ 11?
  • Выбор между vector :: resize () и vector :: reserve ()
  • Как сопоставить вектор значений другому вектору с моей собственной пользовательской картой в R
  • Каков наиболее эффективный способ удаления дубликатов и сортировки вектора?
  • Указатель на вектор
  • Стирание из std :: vector при выполнении для каждого?
  • Инициализация двумерного std :: vector
  • итерация вектора, удаление некоторых элементов, как я иду
  • Вставка элементов в многомерном векторе
  • Interesting Posts

    Неверная операция поперечного streamа: Control ‘textBox1’, доступ к которому осуществляется из streamа, отличного от streamа, который был создан на

    Форматирование номеров страниц в оглавлении для включения текста

    Jquery datepicker – только день и месяц

    Отключить сочетание клавиш Alt + F1 в Cinnamon

    Как отличить несколько клавиатур в Delphi?

    Отображать текущее время в 12-часовом формате с AM / PM

    Могу ли я обернуть каждую строку многострочного текста в промежутке?

    Почему срок жизни не продлевается до срока пребывания объекта-объекта?

    Когда я перезагружаюсь из Linux в Windows, клавиатура и мышь USB не работают

    Есть ли горячая клавиша для значков «Показать рабочий стол» в Windows?

    Лучший способ передачи файлов через локальную сеть между двумя компьютерами Linux

    Случайные данные в модульных тестах?

    File.separator или File.pathSeparator

    Как синхронизировать несколько g-календарей с новым календарем Windows 8?

    Открытый оператор new, частный оператор delete: получение C2248 «не может получить доступ к частному пользователю» при использовании нового

    Давайте будем гением компьютера.