I need to convert a std::array to a std::vector, but I could not find anyway to do it quickly. Here is the sample code:
std::array<char,10> myData={0,1,2,3,4,5,6,7,8,9};
Now I need to create a vector such as:
std::vector<char> myvector;
and initialize it with the array values.
What is the fastest way to do this?
You can use the constructor of std::vector taking iterators.
Constructs the container with the contents of the range [first, last).
e.g.
std::array<char,10> myData = {0,1,2,3,4,5,6,7,8,9};
std::vector<char> myvector(myData.begin(), myData.end());
Just for variety:
std::vector<char> myvector(std::begin(myData), std::end(myData);
std::vector<char> myvector { myData.begin(), myData.end() };
I'd use the range constructor of vector - looking like myvector(myData.begin(), myData.end())
for future reference:
http://en.cppreference.com/w/cpp/container/vector/vector
Related
I want to convert part of a vector to a string, I found this
std::string myString(Buffer.begin(), Buffer.end()); (Buffer is the vector)
But here I converted the whole vector. What the easiest way if I want to skip first 5 chars of the vector and convert the rest? Like ''.join(Buffer[5::]) if it was python.
Just add your offset to begin. Since a vector has random access iterators, you can just use
std::string myString(Buffer.begin() + 5, Buffer.end());
If you are not sure about what type of iterators your container is using, you can use std::next like
std::string myString(std::next(Buffer.begin(), 5), Buffer.end());
which will handle all iterator types, it also may be an O(N) operation.
You also need to make sure that the size of the container is at least 5 before you do this otherwise you'll have undefined behavior if the container is too small.
Like this for example:
if (Buffer.size() >= 5) {
std::string myString(
Buffer.begin() + 5,
Buffer.end());
A more general approach that works with non-random access iterators as well (such as iterators of std::list for example):
std::string myString(
std::next(Buffer.begin(), 5),
Buffer.end());
Or using ranges:
auto subrange = Buffer | std::ranges::views::drop(5);
std::string myString(
std::ranges::begin(subrange),
std::ranges::end(subrange));
A safe (avoiding accesses out of bounds), general approach could be
std::string myString(std::next(Buffer.cbegin(), std::min(5, Buffer.size()),
Buffer.cend()); // ^^^^^^^^^^^^^^^^^^^^^^^^^
i'm trying to extract a subvector of int from another subvector of int using iterator with this code :
std::vector<int> Original;
std::vector<int> NewVec;
NewVec(Original.begin(), Original.begin()+5);
and this doesn't work, only if i declare NewVec in the same line of extraction like that :
std::vector<int> NewVec(Original.begin(), Original.begin()+5);
So, is it possible to use NewVec such that its declaration is before its construction ?
Thanks.
If you want to assign a subrange to an existing std::vector you can use the assign() member:
NewVec.assign(Original.begin(), Original.begin() + 5);
Of course, this assumes that Original has at least 5 elements.
You can use std::copy:
NewVec.reserve(5);
std::copy(std::begin(Original), std::begin(Original)+5,
std::back_inserter(NewVec));
Or std::vector::assign:
NewVec.assign(std::begin(Original), std::begin(Original)+5);
Is there an easy way to add all the elements of a vector to an unordered_set? They are of the same type. Right now, I am using a for loop and was wondering if there is a better way to do it
If you're constructing the unordered_set then:
std::vector<int> v;
std::unordered_set<int> s(v.begin(), v.end());
Forgive me if my syntax has any minor bugs, but you can try the std::copy function, its meant for this purpose.
std::vector<int> v;
std::unordered_set<int> s;
std::copy(v.begin(),v.end(),std::inserter(s,s.end()));
Let's I have
struct Vector {
float i,j,k;
}
I want to zero all elements of vec declared below (i,j,k=0)
std::vector <Vector> vec;
vec.resize(num,0);
I don't want to use reserve() and then push_back() zeroes one by one.
Another thing is, after succesfully initializing vec, I want to set all members of vec to zero again after it is manipulated. Is there something like memset for vectors?
EDIT:
I compared all of the methods in Mike Seymour's and Xeo's answers and as a result
size_t size = vec.size();
vec.clear();
vec.resize(size); is the fastest if they are repeated frequently in a loop.
That's very simple:
vec.resize(num);
or initialise it with the required size:
std::vector<Vector> vec(num);
Both the constructor and resize will fill new elements with value-initialised objects. A value-initialised object of a type with no default constructor (such as your Vector) will have all numeric members initialised to zero.
To reset everything to zero, either
size_t size = vec.size();
vec.clear();
vec.resize(size);
or:
std::fill(vec.begin(), vec.end(), Vector());
or, less efficiently but with a strong exception guarantee:
std::vector<Vector>(vec.size()).swap(vec);
C++ way of setting all current elements to 0:
std::fill( vec.begin(), vec.end(), 0 );
Or, alternatively, to re-initialize to a given size:
vec.clear();
vec.resize(num, 0);
This might not be as performant as memset, but good enough for 99% of the cases.
You can just use memset, so long your Vector is a POD type:
std::vector<Vector> v(num, 0); // inital fill
// do stuff
memset(&v[0], 0, sizeof(Vector) * v.size());
Though the C++ version would be with std::fill
#include <algorithm>
std::fill(v.begin(), v.end(), 0);
Short of (the obvious) building a C style string first then using that to create a std::string, is there a quicker/alternative/"better" way to initialize a string from a vector of chars?
Well, the best way is to use the following constructor:
template<class InputIterator> string (InputIterator begin, InputIterator end);
which would lead to something like:
std::vector<char> v;
std::string str(v.begin(), v.end());
I think you can just do
std::string s( MyVector.begin(), MyVector.end() );
where MyVector is your std::vector.
With C++11, you can do std::string(v.data()) or, if your vector does not contain a '\0' at the end, std::string(v.data(), v.size()).
std::string s(v.begin(), v.end());
Where v is pretty much anything iterable. (Specifically begin() and end() must return InputIterators.)
I like Stefan’s answer (Sep 11 ’13) but would like to make it a bit stronger:
If the vector ends with a null terminator, you should not use (v.begin(), v.end()): you should use v.data() (or &v[0] for those prior to C++17).
If v does not have a null terminator, you should use (v.begin(), v.end()).
If you use begin() and end() and the vector does have a terminating zero, you’ll end up with a string "abc\0" for example, that is of length 4, but should really be only "abc".
Just for completeness, another way is std::string(&v[0]) (although you need to ensure your string is null-terminated and std::string(v.data()) is generally to be preferred.
The difference is that you can use the former technique to pass the vector to functions that want to modify the buffer, which you cannot do with .data().
vector<char> vec;
//fill the vector;
std::string s(vec.begin(), vec.end());