Ответ 1
vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
vector<T> newVec(first, last);
Это операция O (N) для создания нового вектора, но на самом деле нет лучшего способа.
Предположим, что у меня есть std::vector
(назовем его myVec
) размером N
. Самый простой способ построить новый вектор, состоящий из копии элементов X через Y, где 0 <= X <= Y <= N-1 & le; Например, myVec [100000]
через myVec [100999]
в векторе размера 150000
.
Если это невозможно сделать с помощью вектора, есть ли другой тип STL, который я должен использовать вместо этого?
vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
vector<T> newVec(first, last);
Это операция O (N) для создания нового вектора, но на самом деле нет лучшего способа.
Просто используйте векторный конструктор.
std::vector<int> data();
// Load Z elements into data so that Z > Y > X
std::vector<int> sub(&data[100000],&data[101000]);
std::vector(input_iterator, input_iterator)
, в вашем случае foo = std::vector(myVec.begin () + 100000, myVec.begin () + 150000);
, см., например, здесь
В наши дни мы используем 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());
Примечание:
gsl
расшифровывается как Библиотека поддержки руководящих принципов. Для получения дополнительной информации о gsl
см.: http://www.modernescpp.com/index.php/c-core-guideline-the-guidelines-support-library.gsl
см.: https://github.com/Microsoft/GSLspan
. Вы бы использовали std::span
и #include <span>
, а не #include <gsl/span>
.std::vector
имеет конструктор gazillion, очень легко попасть в тот, который вы не собирались использовать, так что будьте осторожны.Если оба варианта не будут изменены (добавление/удаление элементов - изменение существующих - отлично, если вы уделяете внимание проблемам с потоками), вы можете просто обойти data.begin() + 100000
и data.begin() + 101000
и сделать вид, что они являются begin()
и end()
меньшего вектора.
Или, поскольку векторное хранилище гарантировано будет смежным, вы можете просто передать массив из 1000 элементов:
T *arrayOfT = &data[0] + 100000;
size_t arrayOfTLength = 1000;
Обе эти методы занимают постоянное время, но требуют, чтобы длина данных не увеличивалась, вызывая перераспределение.
Вы не указали, какой тип 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
Вы можете использовать копию STL с производительностью O (M), когда M - размер подвектора.
Ok. Это довольно старая дискуссия. Но я только что обнаружил что-то опрятное:
slice_array - Может ли это быть быстрой альтернативой? Я не тестировал его.
Единственный способ проецировать коллекцию, которая не является линейным, - это сделать это лениво, где полученный "вектор" на самом деле является подтипом, который делегирует оригинальную коллекцию. Например, метод Scala List#subseq
создает подпоследовательность в постоянное время. Тем не менее, это работает только в том случае, если коллекция является неизменной и если основной язык занимается сбором мусора.
Вы можете просто использовать insert
vector<type> myVec { n_elements };
vector<type> newVec;
newVec.insert(newVec.begin(), myVec.begin() + X, myVec.begin() + Y);
Проводя это поздно только для других. Я ставлю, что первый кодер уже сделан. Для простых типов данных копия не требуется, просто верните старые добрые методы кода 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
Возможно, array_view/span в библиотеке GSL является хорошим вариантом.
Вот также одна реализация файла: array_view.
Легко копируйте элементы из одного вектора в другой
В этом примере я использую вектор пар, чтобы было легче понять
'
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
Еще один вариант: полезен, например, при перемещении между 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));