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
Best way to extract a subvector from a vector?
提问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
回答by einpoklum
These days, we use span
s! So you would write:
这些天,我们使用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);
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:
笔记:
gsl
stands for Guidelines Support Library. For more information aboutgsl
, see: http://www.modernescpp.com/index.php/c-core-guideline-the-guidelines-support-library.- For one implementation of
gsl
, see: https://github.com/Microsoft/GSL - C++20 provides an implementation of
span
. You would usestd::span
and#include <span>
rather than#include <gsl/span>
. - For more information about spans, see: What is a "span" and when should I use one?
std::vector
has a gazillion constructors, it's super-easy to fall into one you didn't intend to use, so be careful.
gsl
代表指南支持库。有关 的更多信息gsl
,请参阅:http: //www.modernescpp.com/index.php/c-core-guideline-the-guidelines-support-library。- 对于 的一种实现
gsl
,请参见:https: //github.com/Microsoft/GSL - C++20 提供了
span
. 您将使用std::span
and#include <span>
而不是#include <gsl/span>
。 - 有关跨度的更多信息,请参阅:什么是“跨度”以及何时应该使用?
std::vector
有无数的构造函数,很容易陷入你不打算使用的构造函数中,所以要小心。
回答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() + 100000
and data.begin() + 101000
, and pretend that they are the begin()
and end()
of a smaller vector.
如果两者都不会被修改(不添加/删除项目 - 只要您注意线程问题,修改现有项目就可以了),您可以简单地传递data.begin() + 100000
and 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<...> myVec
is, 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> myVec
where type
in this case is int
:
你没有提到什么是类型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
回答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
回答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#subseq
method 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
方法在恒定时间内创建一个子序列。但是,这仅在集合不可变且底层语言进行垃圾收集时才有效。