假设我有一个大小为std::vector
的{{1}}(我们称之为myVec
)。构造由元素X到Y的副本组成的新向量的最简单方法是什么,其中0 <= X <= Y <= N-1?例如,N
到myVec [100000]
的大小为myVec [100999]
的向量中的150000
。
如果使用向量无法有效地完成此操作,是否应该使用另一种STL数据类型?
答案 0 :(得分:305)
vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
vector<T> newVec(first, last);
构造新向量是一个O(N)操作,但实际上没有更好的方法。
答案 1 :(得分:77)
只需使用矢量构造函数。
std::vector<int> data();
// Load Z elements into data so that Z > Y > X
std::vector<int> sub(&data[100000],&data[101000]);
答案 2 :(得分:24)
std::vector(input_iterator, input_iterator)
,在您的情况foo = std::vector(myVec.begin () + 100000, myVec.begin () + 150000);
中,请参阅here
答案 3 :(得分:11)
现在,我们使用varying vec4 vColor;
varying vec2 vTexCoord;
uniform sampler2D u_texture; //diffuse map
uniform sampler2D u_normals; //normal map
uniform sampler2D u_light; //light map
uniform vec2 resolution; //resolution of screen
uniform vec3 lightPos; //light position, normalized
uniform vec4 lightColor; //light RGBA -- alpha is intensity
uniform vec4 ambientColor; //ambient RGBA -- alpha is intensity
void main() {
//RGBA of our diffuse color
vec4 diffuseColor = texture2D(u_texture, vTexCoord);
//RGB of our normal map
vec3 normalMap = texture2D(u_normals, vTexCoord).rgb;
//NormalMap.g = 1.0 - NormalMap.g;
//The delta position of light
vec3 lightDir = vec3(lightPos.xy - (gl_FragCoord.xy / resolution.xy), lightPos.z);
lightDir.x *= resolution.x / resolution.y;
//normalize our vectors
vec3 N = normalize(normalMap * 2.0 - 1.0);
vec3 L = normalize(lightDir);
//Pre-multiply light color with intensity
//Then perform "N dot L" to determine our diffuse term
vec3 diffuse = (lightColor.rgb * lightColor.a) * max(dot(N, L), 0.0);
//pre-multiply ambient color with intensity
vec3 ambient = ambientColor.rgb * ambientColor.a;
//calculate attenuation from lightmap
vec2 lighCoord = (gl_FragCoord.xy / resolution.xy);
vec3 attenuation = texture2D(u_light, lighCoord).rgb;
//the calculation which brings it all together
vec3 intensity = ambient + diffuse * attenuation;
vec3 finalColor = diffuseColor.rgb * intensity;
gl_FragColor = vColor * vec4(finalColor, diffuseColor.a);
}
s!所以你会写:
span
获得与#include <gsl/span>
...
auto start_pos = 100000;
auto length = 1000;
auto my_subspan = gsl::make_span(myvec).subspan(start_pos, length);
相同类型的1000个元素的范围。现在,这是不是副本,它只是向量中数据的视图,所以要小心。如果你想要一个实际的副本,你可以这样做:
myvec
注意:
std::vector<T> new_vec(my_subspan.cbegin(), my_subspan.cend());
代表指南支持库。有关gsl
的详细信息,请参阅:http://www.modernescpp.com/index.php/c-core-guideline-the-guidelines-support-library。gsl
的一个实现,请参阅:https://github.com/Microsoft/GSL gsl
的实现。您可以使用span
和std::span
而不是#include <span>
。#include <gsl/span>
有很多建造者,很容易陷入你不打算使用的那个,所以要小心。答案 4 :(得分:10)
如果两者都不会被修改(没有添加/删除项目 - 只要您注意线程问题,修改现有项目就可以了),您可以简单地传递data.begin() + 100000
和data.begin() + 101000
,并假装它们是较小向量的begin()
和end()
。
或者,由于矢量存储保证是连续的,您可以简单地传递1000个项目数组:
T *arrayOfT = &data[0] + 100000;
size_t arrayOfTLength = 1000;
这两种技术都需要一段时间,但要求数据长度不会增加,从而触发重新分配。
答案 5 :(得分:6)
你没有提到<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView android:id="@android:id/list" android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<com.gc.materialdesign.views.ProgressBarCircularIndeterminate
android:id="@+id/progressBarCircularIndeterminate"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="#1E88E5" />
</FrameLayout>
是什么类型,但是如果它是一个不包含指针的简单类型或结构/类,并且你想要最好的效率,那么你可以做一个直接的内存复制(我认为这将比提供的其他答案更快)。以下是std::vector<...> myVec
的一般示例,其中std::vector<type> myVec
在这种情况下为type
:
int
答案 6 :(得分:3)
当M是子向量的大小时,您可以将STL copy与O(M)性能结合使用。
答案 7 :(得分:1)
投影非线性时间集合的唯一方法是懒散地进行,其中生成的“向量”实际上是委托给原始集合的子类型。例如,Scala的List#subseq
方法在恒定时间内创建子序列。但是,这仅在集合不可变且基础语言运行垃圾收集时才有效。
答案 8 :(得分:1)
确定。这是一个非常古老的讨论。但我刚刚发现了一些整洁的东西:
slice_array - 这可能是一个快速的选择吗?我还没有测试过。
答案 9 :(得分:1)
此讨论已经很久了,但是尚未提及最简单的讨论,list-initialization:
vector<int> subvector = {big_vector.begin() + 3, big_vector.end() - 2};
它需要c ++ 11或更高版本。
用法示例:
#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;
}
结果:
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;
答案 10 :(得分:0)
仅为其他人发布这个晚了。我打赌第一个编码器现在完成了。 对于简单的数据类型,不需要复制,只需恢复到良好的旧C代码方法。
std::vector <int> myVec;
int *p;
// Add some data here and set start, then
p=myVec.data()+start;
然后将指针p和len传递给需要子向量的任何东西。
必须是!!len < myVec.size()-start
答案 11 :(得分:0)
也许GSL库中的array_view/span是一个不错的选择。
这也是单个文件的实现:array_view。
答案 12 :(得分:0)
轻松地将元素从一个向量复制到另一向量
在这个例子中,我使用成对向量使它易于理解
`
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
答案 13 :(得分:0)
另一个选择:
例如,在无法使用构造函数的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));
答案 14 :(得分:0)
您可以只使用insert
vector<type> myVec { n_elements };
vector<type> newVec;
newVec.insert(newVec.begin(), myVec.begin() + X, myVec.begin() + Y);