C++ 从向量中提取子向量的最佳方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/421573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:15:27  来源:igfitidea点击:

Best way to extract a subvector from a vector?

c++stlvectorrange

提问by An???drew

Suppose I have a std::vector(let's call it myVec) of size N. What's the simplest way to construct a new vector consisting of a copy of elements X through Y, where 0 <= X <= Y <= N-1? For example, myVec [100000]through myVec [100999]in a vector of size 150000.

假设我有一个std::vector(我们称之为myVec) size N。构造由元素 X 到 Y 的副本组成的新向量的最简单方法是什么,其中 0 <= X <= Y <= N-1?例如,myVec [100000]通过myVec [100999]大小为 的向量150000

If this cannot be done efficiently with a vector, is there another STL datatype that I should use instead?

如果这不能用向量有效地完成,我应该使用另一种 STL 数据类型吗?

回答by Greg Rogers

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

It's an O(N) operation to construct the new vector, but there isn't really a better way.

构造新向量是一个 O(N) 操作,但实际上没有更好的方法。

回答by Martin York

Just use the vector constructor.

只需使用向量构造函数。

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

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

回答by Anteru

std::vector(input_iterator, input_iterator), in your case foo = std::vector(myVec.begin () + 100000, myVec.begin () + 150000);, see for example here

std::vector(input_iterator, input_iterator),就您而言foo = std::vector(myVec.begin () + 100000, myVec.begin () + 150000);,请参见此处的示例

回答by einpoklum

These days, we use spans! So you would write:

这些天,我们使用spans! 所以你会写:

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

to get a span of 1000 elements of the same type as myvec's. Or a more terse form:

获得与myvec's相同类型的 1000 个元素的跨度。或者更简洁的形式:

auto my_subspan = gsl::make_span(myvec).subspan(1000000, 1000);

(but I don't like this as much, since the meaning of each numeric argument is not entirely clear; and it gets worse if the length and start_pos are of the same order of magnitude.)

(但我不太喜欢这个,因为每个数字参数的含义并不完全清楚;如果长度和 start_pos 的数量级相同,情况会变得更糟。)

Anyway, remember that this is not a copy, it's just a viewof the data in the vector, so be careful. If you want an actual copy, you could do:

无论如何,请记住这不是副本,它只是向量中数据的视图,所以要小心。如果你想要一个实际的副本,你可以这样做:

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

Notes:

笔记:

回答by Eclipse

If both are not going to be modified (no adding/deleting items - modifying existing ones is fine as long as you pay heed to threading issues), you can simply pass around data.begin() + 100000and data.begin() + 101000, and pretend that they are the begin()and end()of a smaller vector.

如果两者都不会被修改(不添加/删除项目 - 只要您注意线程问题,修改现有项目就可以了),您可以简单地传递data.begin() + 100000and data.begin() + 101000,并假装它们是较小向量的begin()and end()

Or, since vector storage is guaranteed to be contiguous, you can simply pass around a 1000 item array:

或者,由于保证向量存储是连续的,您可以简单地传递一个 1000 个项目的数组:

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

Both these techniques take constant time, but require that the length of data doesn't increase, triggering a reallocation.

这两种技术都需要恒定的时间,但要求数据长度不会增加,从而触发重新分配。

回答by MasterHD

You didn't mention what type std::vector<...> myVecis, but if it's a simple type or struct/class that doesn't include pointers, and you want the best efficiency, then you can do a direct memory copy (which I think will be faster than the other answers provided). Here is a general example for std::vector<type> myVecwhere typein this case is int:

你没有提到什么是类型std::vector<...> myVec,但是如果它是一个不包含指针的简单类型或结构/类,并且你想要最好的效率,那么你可以进行直接内存复制(我认为这会比提供其他答案)。这是在这种情况下std::vector<type> myVec在哪里的一般示例:typeint

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

回答by David Tóth

This discussion is pretty old, but the simplest one isn't mentioned yet, with list-initialization:

这个讨论已经很老了,但还没有提到最简单的,使用列表初始化

 vector<int> subvector = {big_vector.begin() + 3, big_vector.end() - 2}; 

It requires c++11 or above.

它需要 c++11 或更高版本。

Example usage:

用法示例:

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

using namespace std;

int main(){

    vector<int> big_vector = {5,12,4,6,7,8,9,9,31,1,1,5,76,78,8};
    vector<int> subvector = {big_vector.begin() + 3, big_vector.end() - 2};

    cout << "Big vector: ";
    for_each(big_vector.begin(), big_vector.end(),[](int number){cout << number << ";";});
    cout << endl << "Subvector: ";
    for_each(subvector.begin(), subvector.end(),[](int number){cout << number << ";";});
    cout << endl;
}

Result:

结果:

Big vector: 5;12;4;6;7;8;9;9;31;1;1;5;76;78;8;
Subvector: 6;7;8;9;9;31;1;1;5;76;

回答by Matheus Vinícius de Andrade

You could just use insert

你可以用 insert

vector<type> myVec { n_elements };

vector<type> newVec;

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

回答by Yuval F

You can use STL copywith O(M) performance when M is the size of the subvector.

当 M 是子向量的大小时,您可以使用具有 O(M) 性能的STL 复制

回答by Daniel Spiewak

The only way to project a collection that is not linear time is to do so lazily, where the resulting "vector" is actually a subtype which delegates to the original collection. For example, Scala's List#subseqmethod create a sub-sequence in constant time. However, this only works if the collection is immutable and if the underlying language sports garbage collection.

投影不是线性时间的集合的唯一方法是懒惰地这样做,其中生成的“向量”实际上是委托给原始集合的子类型。例如,Scala 的List#subseq方法在恒定时间内创建一个子序列。但是,这仅在集合不可变且底层语言进行垃圾收集时才有效。