내가 size std::vector
()라고 가정 해보십시오 . 0 <= X <= Y <= N-1 인 요소 X부터 Y까지의 복사본으로 구성된 새 벡터를 구성하는 가장 간단한 방법은 무엇입니까? 예를 들어 size의 벡터를 통해 통과 합니다 .myVec
N
myVec [100000]
myVec [100999]
150000
벡터로 효율적으로 수행 할 수없는 경우 대신 사용해야하는 다른 STL 데이터 유형이 있습니까?
내가 size std::vector
()라고 가정 해보십시오 . 0 <= X <= Y <= N-1 인 요소 X부터 Y까지의 복사본으로 구성된 새 벡터를 구성하는 가장 간단한 방법은 무엇입니까? 예를 들어 size의 벡터를 통해 통과 합니다 .myVec
N
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) 연산이지만 실제로 더 좋은 방법은 없습니다.
O(Y-X)
이라고 말합니다 O(Z) where Z=Y-X
.
vector<T> newVec(myVec.begin() + 100000, myVec.begin() + 101000);
?
벡터 생성자를 사용하십시오.
std::vector<int> data();
// Load Z elements into data so that Z > Y > X
std::vector<int> sub(&data[100000],&data[101000]);
operator[]
참조 를 반환 한다는 것을 기억하십시오 . 액세스 위반이 될 수있는 참조를 읽거나 쓰는 시점에만 있습니다. 우리는 주소를 얻지 않고 대신 얻었으므로 UB를 호출하지 않았습니다.
std::vector<T>(input_iterator, input_iterator)
귀하의 경우 foo = std::vector<T>(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
. 또는 더 간결한 형태 :
auto my_subspan = gsl::make_span(myvec).subspan(1000000, 1000);
(그러나 각 숫자 인수의 의미가 완전히 명확하지 않기 때문에 나는 이것을 좋아하지 않습니다. 길이와 start_pos가 동일한 크기의 순서이면 더 나빠집니다.)
어쨌든 이것은 복사본 이 아니라 벡터의 데이터 보기 일 뿐이 므로주의하십시오. 실제 사본을 원할 경우 다음을 수행 할 수 있습니다.
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
참조 하십시오 .gsl
대해서는 https://github.com/Microsoft/GSL을 참조하십시오.span
. 당신이 사용하는 것이 std::span
및 #include <span>
보다는 #include <gsl/span>
.std::vector
gazillion 생성자가 있으므로 사용하지 않으려는 생성기에 빠지기 쉽기 때문에 조심하십시오.cbegin
하고 cend
;) std::cbegin
등도.
모두 수정하지 않을 경우 (항목이 추가 / 삭제 - 기존 수정하는만큼 당신이 스레딩 문제에주의를 지불로 괜찮습니다)을, 당신은 단순히 주변에 통과 할 수 data.begin() + 100000
와 data.begin() + 101000
, 그들이있는 척 begin()
하고 end()
작은 벡터.
또는 벡터 스토리지는 연속적으로 보장되므로 1000 개의 항목 배열을 전달할 수 있습니다.
T *arrayOfT = &data[0] + 100000;
size_t arrayOfTLength = 1000;
이 두 기술 모두 일정한 시간이 걸리지 만 데이터 길이가 늘어나지 않아 재 할당이 트리거되어야합니다.
이 토론은 꽤 오래되었지만 목록 초기화 와 함께 가장 간단한 것은 아직 언급되지 않았습니다 .
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;
유형 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
std::vector(myVec.begin () + 100000, myVec.begin () + 150000);
인 -O3을 사용 하면이 생산물의 더 긴 버전이 정확히 동일한 어셈블리로 만들어지지 않을지 궁금합니다 .
std::vector<>(iter, iter)
에 memmove()
, 적절한 경우 (사소한 생성자의 적절한 정의는 사소한 경우).
memcpy
. DO가 std::copy
범위 (두 반복자를) 수락하거나 생성자 및 컴파일러와 std.library는 전화를 공모 할 memcpy
때 적합합니다.
당신은 그냥 사용할 수 있습니다 insert
vector<type> myVec { n_elements };
vector<type> newVec;
newVec.insert(newVec.begin(), myVec.begin() + X, myVec.begin() + Y);
M이 서브 벡터의 크기 인 경우 O (M) 성능과 함께 STL 복사 를 사용할 수 있습니다 .
newvec.reserve(10100 - 10000);
. IT는 분명히 옵션이며 기술적으로 작동합니다. 그러나 두 가지 중에서 추천 할 것입니까?
선형 시간이 아닌 컬렉션을 투영하는 유일한 방법은 느리게 만드는 것입니다. 결과 "벡터"는 실제로 원래 컬렉션에 위임하는 하위 유형입니다. 예를 들어 Scala의 List#subseq
방법은 일정한 시간에 하위 시퀀스를 만듭니다. 그러나 이것은 컬렉션이 변경 불가능하고 기본 언어가 스포츠 가비지 수집 인 경우에만 작동합니다.
다른 사람들을 위해 이것을 늦게 게시합니다. 나는 첫 번째 코더가 지금 끝날 것이라고 확신합니다. 간단한 데이터 유형의 경우 복사가 필요하지 않으며 오래된 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
GSL 라이브러리 의 array_view / span 이 좋은 옵션 일 수 있습니다.
여기에 하나의 파일 구현도 : 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
또 다른 옵션 : 예를 들어 생성자를 사용할 수없는 a thrust::device_vector
와 a 사이를 이동할 때 유용합니다 thrust::host_vector
.
std::vector<T> newVector;
newVector.reserve(1000);
std::copy_n(&vec[100000], 1000, std::back_inserter(newVector));
복잡성이어야 함 O (N)
이것을 상위 Anwer 코드와 결합 할 수 있습니다
vector<T>::const_iterator first = myVec.begin() + 100000;
vector<T>::const_iterator last = myVec.begin() + 101000;
std::copy(first, last, std::back_inserter(newVector));