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

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

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

вопрос задан 7.01.2009
An̲̳̳drew
5601 репутация

13 ответов


  • 264 рейтинг
    vector::const_iterator first = myVec.begin() + 100000;
    vector::const_iterator last = myVec.begin() + 101000;
    vector newVec(first, last);
    

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

    ответ дан Greg Rogers, с репутацией 26646, 7.01.2009
  • 63 рейтинг

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

    std::vector   data();
    // Load Z elements into data so that Z > Y > X
    
    std::vector   sub(&data[100000],&data[101000]);
    
    ответ дан Martin York, с репутацией 192044, 7.01.2009
  • 23 рейтинг

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

    ответ дан Anteru, с репутацией 14346, 7.01.2009
  • 10 рейтинг

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

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

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

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

    ответ дан Eclipse, с репутацией 37935, 7.01.2009
  • 6 рейтинг

    Вы не упомянули, что такое тип std::vector<...> myVec, но если это простой тип или структура / класс, не содержащие указателей, и вы хотите добиться максимальной эффективности, то вы можете сделать прямое копирование памяти (что, я думаю, будет быстрее). чем другие ответы, представленные). Вот общий пример для std::vector 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 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
    
    ответ дан MasterHD, с репутацией 1138, 16.10.2015
  • 4 рейтинг

    В эти дни мы используем span с! Итак, вы бы написали:

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

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

    std::vector new_vec(my_subspan.begin(), my_subspan.end());
    

    Примечания:

    ответ дан einpoklum, с репутацией 30565, 9.08.2017
  • 3 рейтинг

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

    ответ дан Yuval F, с репутацией 18965, 7.01.2009
  • 1 рейтинг

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

    ответ дан Daniel Spiewak, с репутацией 45679, 7.01.2009
  • 0 рейтинг

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

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

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

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

    vector::const_iterator first = myVec.begin() + 100000;
    vector::const_iterator last = myVec.begin() + 101000;
    std::copy(first, last, std::back_inserter(newVector));
    
    ответ дан JHBonarius, с репутацией 3519, 29.06.2018
  • 0 рейтинг

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

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

    ответ дан myd7349, с репутацией 1, 27.04.2017
  • 0 рейтинг

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

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

    ответ дан umayfindurself, с репутацией 82, 11.09.2013
  • 0 рейтинг

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

    vector > v(n);
    
    //we want half of elements in vector a and another half in vector b
    vector > a(v.begin(),v.begin()+n/2);
    vector > 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 > a(v.begin()+10, v.begin+16);
    

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

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

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

    ответ дан Jishu Dohare, с репутацией 1, 24.06.2018
  • 0 рейтинг

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

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

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

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

    ответ дан mrrgu, с репутацией 21, 18.11.2013