2015-01-18 4 views
4

Интересно, что было бы правильным способом заменить (переписать) часть заданного входа std :: vector другим, меньшим std :: vector? Я не хочу оставлять остальную часть исходного вектора неизменной. Также мне не нужно беспокоиться о том, что было в исходном векторе, и Мне больше не нужно сохранять меньший вектор.Замена части std :: vector на меньшую std :: vector

Скажем, у меня есть это:

std::vector<int> input = { 0, 0, 1, 1, 2, 22, 3, 33, 99 }; 
std::vector<int> a = { 1, 2, 3 }; 
std::vector<int> b = { 4, 5, 6, 7, 8 }; 

И я хочу, чтобы добиться того, что:

input = { 1, 2, 3, 4, 5, 6, 7, 8, 99} 

Что такое правильный способ сделать это? Я думал, что-то вроде

input.replace(input.beginn(), input.beginn()+a.size(), a); 

// промежуточного входа будет выглядеть так: вход = {1, 2, 3, 1, 2, 22, 3, 33, 99};

input.replace(input.beginn()+a.size(), input.beginn()+a.size()+b.size(), b); 

Должен быть стандартный способ сделать это, не так ли? Мои мысли по этому поводу до сих пор являются следующие:

  • Я не могу использовать зЬй :: вектор :: назначьте для него разрушает все элементы ввода
  • станд :: вектор :: push_back не заменит, но увеличить вход -> не то, что я хочу

  • std :: vector :: insert также создает новые элементы и увеличивает входной вектор, но я точно знаю, что векторы a.size() + b.size() < = input.size()

  • std :: vector :: swap не будет работать с тех пор есть некоторый контент ввода, который должен оставаться там (в примере последний элемент) также не будет работать, чтобы добавить b таким образом
  • std :: vector :: emplace также увеличивает input.size -> кажется неправильным, поскольку скважина

Также я бы предпочел, чтобы решение не утрачивало производительность путем ненужных очищений или записи значений в векторы a или b. Мои векторы будут очень большими для реального, и это в конечном итоге о производительности.

Любая компетентная помощь будет очень признательна.

+2

Вы ищете ['std :: copy'] (http://en.cppreference.com/w/cpp/algorithm/copy)? Если я правильно понял ваш вопрос (не уверен), то [это] (http://coliru.stacked-crooked.com/a/755867ac783ad0a7) должен быть тем, что вы хотите. Если да, дайте мне знать, и я отправлю его в качестве ответа. –

+0

Кажется, что я нахожусь, хотя я не совсем понимаю это полностью. С копией OutputIt (сначала InputIt, InputIt last, OutputIt d_first); было бы: first = a.beginn(), last = a.end() d_first = input.beginn() также я не могу понять значение «Для функции std :: copy d_first не должно быть в диапазон [первый, последний]. std :: copy_backward должен использоваться в этом случае. » – Simeon

ответ

6

Вы, кажется, после того, как std::copy().Это, как вы будете использовать его в вашем примере (live demo on Coliru):

#include <algorithm> // Necessary for `std::copy`... 

// ... 

std::vector<int> input = { 0, 0, 1, 1, 2, 22, 3, 33, 99 }; 
std::vector<int> a = { 1, 2, 3 }; 
std::vector<int> b = { 4, 5, 6, 7, 8 };  

std::copy(std::begin(a), std::end(a), std::begin(input)); 
std::copy(std::begin(b), std::end(b), std::begin(input) + a.size()); 

Как Zyx2000 отмечает in the comments, в этом случае вы можете также использовать итератор, возвращаемый первым вызовом std::copy() в качестве точки вставки для следующей копии :

auto last = std::copy(std::begin(a), std::end(a), std::begin(input)); 
std::copy(std::begin(b), std::end(b), last); 

Таким образом, итераторы произвольного доступа больше не требуется - это был тот случай, когда у нас было выражение std::begin(input) + a.size().

Первые два аргумента std::copy() обозначают исходный диапазон элементов, которые вы хотите скопировать. Третий аргумент - это итератор первого элемента, который вы хотите переписать в контейнере назначения.

При использовании std::copy() убедитесь, что контейнер назначения достаточно велик, чтобы разместить количество элементов, которые вы собираетесь скопировать.

Кроме того, источник и целевой диапазон не должны чередоваться.

+2

Код можно сделать более общим, заменив 'std :: begin (input) + a.size()' с возвращаемым значением первого вызова на 'std :: copy'. Затем он работает, даже если итераторы не являются итераторами произвольного доступа ([Пример] (http://coliru.stacked-crooked.com/a/25c25acf94ad0807)). –

+0

@ Zyx2000: Правильно, хорошо! –

0

Попробуйте это:

#include <iostream> 
#include <vector> 
#include <algorithm> 

int main() { 
    std::vector<int> input = { 0, 0, 1, 1, 2, 22, 3, 33, 99 }; 
    std::vector<int> a = { 1, 2, 3 }; 
    std::vector<int> b = { 4, 5, 6, 7, 8 }; 

    std::set_union(a.begin(), a.end(), b.begin(), b.end(), input.begin()); 

    for (std::vector<int>::const_iterator iter = input.begin(); 
      iter != input.end(); 
      ++iter) 
    { 
     std::cout << *iter << " "; 
    } 

    return 0; 
} 

Он выводит:

1 2 3 4 5 6 7 8 99 
+0

Я еще не уверен на 100%, но это не кажется правильным ответом. Я не могу гарантировать, что a и b всегда упорядочены или что входные элементы, которые должны оставаться, больше, чем все предыдущие. Также я хотел бы сохранить минимальное количество записи и memmory, поскольку я мог бы использовать векторы очень большого размера. Повторное использование ввода избавит меня от дополнительного распределения памяти, поскольку выход будет иметь тот же размер, что и вход, который больше не нужен. – Simeon

+0

OK, проблем нет. Я оставлю этот ответ в любом случае .... если я не получаю downvotes ... Спасибо за комментарий! – jpo38

Смежные вопросы