Лучший способ извлечь подвектор из вектора?

Предположим, что у меня есть std::vector (назовем его myVec) размером N. Самый простой способ построить новый вектор, состоящий из копии элементов X через Y, где 0 <= X <= Y <= N-1 & le; Например, myVec [100000] через myVec [100999] в векторе размера 150000.

Если это невозможно сделать с помощью вектора, есть ли другой тип STL, который я должен использовать вместо этого?

Ответ 1

vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
vector<T> newVec(first, last);

Это операция O (N) для создания нового вектора, но на самом деле нет лучшего способа.

Ответ 2

Просто используйте векторный конструктор.

std::vector<int>   data();
// Load Z elements into data so that Z > Y > X

std::vector<int>   sub(&data[100000],&data[101000]);

Ответ 3

std::vector(input_iterator, input_iterator), в вашем случае foo = std::vector(myVec.begin () + 100000, myVec.begin () + 150000);, см., например, здесь

Ответ 4

В наши дни мы используем span s! Так что вы бы написали:

#include <gsl/span>

...
auto start_pos = 100000;
auto length = 1000;
auto span_of_myvec = gsl::make_span(myvec);
auto my_subspan = span_of_myvec.subspan(start_pos, length);

чтобы получить диапазон из 1000 элементов того же типа, что и у myvec. Теперь это не копия, это просто представление данных в векторе, поэтому будьте осторожны. Если вам нужна реальная копия, вы можете сделать:

std::vector<T> new_vec(my_subspan.cbegin(), my_subspan.cend());

Примечание:

Ответ 5

Если оба варианта не будут изменены (добавление/удаление элементов - изменение существующих - отлично, если вы уделяете внимание проблемам с потоками), вы можете просто обойти data.begin() + 100000 и data.begin() + 101000 и сделать вид, что они являются begin() и end() меньшего вектора.

Или, поскольку векторное хранилище гарантировано будет смежным, вы можете просто передать массив из 1000 элементов:

T *arrayOfT = &data[0] + 100000;
size_t arrayOfTLength = 1000;

Обе эти методы занимают постоянное время, но требуют, чтобы длина данных не увеличивалась, вызывая перераспределение.

Ответ 6

Вы не указали, какой тип std::vector<...> myVec есть, но если это простой тип или структура/класс, который не содержит указателей, и вы хотите получить лучшую эффективность, то вы можете сделать копию с прямой памятью (что я думаю, будет быстрее, чем другие ответы). Вот общий пример для std::vector<type> myVec, где type в этом случае int:

typedef int type; //choose your custom type/struct/class
int iFirst = 100000; //first index to copy
int iLast = 101000; //last index + 1
int iLen = iLast - iFirst;
std::vector<type> newVec;
newVec.resize(iLen); //pre-allocate the space needed to write the data directly
memcpy(&newVec[0], &myVec[iFirst], iLen*sizeof(type)); //write directly to destination buffer from source buffer

Ответ 7

Вы можете использовать копию STL с производительностью O (M), когда M - размер подвектора.

Ответ 8

Ok. Это довольно старая дискуссия. Но я только что обнаружил что-то опрятное:

slice_array - Может ли это быть быстрой альтернативой? Я не тестировал его.

Ответ 9

Единственный способ проецировать коллекцию, которая не является линейным, - это сделать это лениво, где полученный "вектор" на самом деле является подтипом, который делегирует оригинальную коллекцию. Например, метод Scala List#subseq создает подпоследовательность в постоянное время. Тем не менее, это работает только в том случае, если коллекция является неизменной и если основной язык занимается сбором мусора.

Ответ 10

Вы можете просто использовать insert

vector<type> myVec { n_elements };

vector<type> newVec;

newVec.insert(newVec.begin(), myVec.begin() + X, myVec.begin() + Y);

Ответ 11

Проводя это поздно только для других. Я ставлю, что первый кодер уже сделан. Для простых типов данных копия не требуется, просто верните старые добрые методы кода C.

std::vector <int>   myVec;
int *p;
// Add some data here and set start, then
p=myVec.data()+start;

Затем передайте указатель p и len на все, что нужно для подвектора.

notelen должно быть!! len < myVec.size()-start

Ответ 12

Возможно, array_view/span в библиотеке GSL является хорошим вариантом.

Вот также одна реализация файла: array_view.

Ответ 13

Легко копируйте элементы из одного вектора в другой
В этом примере я использую вектор пар, чтобы было легче понять
'

vector<pair<int, int> > v(n);

//we want half of elements in vector a and another half in vector b
vector<pair<lli, lli> > a(v.begin(),v.begin()+n/2);
vector<pair<lli, lli> > b(v.begin()+n/2, v.end());


//if v = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
//then a = [(1, 2), (2, 3)]
//and b = [(3, 4), (4, 5), (5, 6)]

//if v = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7)]
//then a = [(1, 2), (2, 3), (3, 4)]
//and b = [(4, 5), (5, 6), (6, 7)]

'
Как вы можете видеть, вы можете легко копировать элементы из одного вектора в другой, если вы хотите скопировать элементы из индекса с 10 по 16, например, мы бы использовали

vector<pair<int, int> > a(v.begin()+10, v.begin+16);

и если вы хотите, чтобы элементы от индекса 10 до некоторого индекса от конца, то в этом случае

vector<pair<int, int> > a(v.begin()+10, v.end()-5);

надеюсь, это поможет, просто запомните в последнем случае v.end()-5 > v.begin()+10

Ответ 14

Еще один вариант: полезен, например, при перемещении между thrust::device_vector и thrust::host_vector, где вы не можете использовать конструктор.

std::vector<T> newVector;
newVector.reserve(1000);
std::copy_n(&vec[100000], 1000, std::back_inserter(newVector));

Также должна быть сложность O (N)

Вы можете комбинировать это с верхним кодом ответа

vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
std::copy(first, last, std::back_inserter(newVector));