In my C++ code,
vector <string> strVector = GetStringVector();
vector <int> intVector = GetIntVector();
So I combined these two vectors into a single one,
void combineVectors(vector<string>& strVector, vector <int>& intVector, vector < pair <string, int>>& pairVector)
{
for (int i = 0; i < strVector.size() || i < intVector.size(); ++i )
{
pairVector.push_back(pair<string, int> (strVector.at(i), intVector.at(i)));
}
}
Now this function is called like this,
vector <string> strVector = GetStringVector();
vector <int> intVector = GetIntVector();
vector < pair <string, int>> pairVector
combineVectors(strVector, intVector, pairVector);
//rest of the implementation
The combineVectors function uses a loop to add the elements of other 2 vectors to the vector pair. I doubt this is a efficient way as this function gets called hundrands of times passing different data. This might cause a performance issue because everytime it goes through the loop.
My goal is to copy both the vectors in "one go" to the vector pair. i.e., without using a loop. Am not sure whether that's even possible.
Is there a better way of achieving this without compromising the performance?
You have clarified that the arrays will always be of equal size. That's a prerequisite condition.
So, your situation is as follows. You have vector A over here, and vector B over there. You have no guarantees whether the actual memory that vector A uses and the actual memory that vector B uses are next to each other. They could be anywhere.
Now you're combining the two vectors into a third vector, C. Again, no guarantees where vector C's memory is.
So, you have really very little to work with, in terms of optimizations. You have no additional guarantees whatsoever. This is pretty much fundamental: you have two chunks of bytes, and those two chunks need to be copied somewhere else. That's it. That's what has to be done, that's what it all comes down to, and there is no other way to get it done, other than doing exactly that.
But there is one thing that can be done to make things a little bit faster. A vector will typically allocate memory for its values in incremental steps, reserving some extra space, initially, and as values get added to the vector, one by one, and eventually reach the vector's reserved size, the vector has to now grab a new larger block of memory, copy everything in the vector to the larger memory block, then delete the older block, and only then add the next value to the vector. Then the cycle begins again.
But you know, in advance, how many values you are about to add to the vector, so you simply instruct the vector to reserve() enough size in advance, so it doesn't have to repeatedly grow itself, as you add values to it. Before your existing for loop, simply:
pairVector.reserve(pairVector.size()+strVector.size());
Now, the for loop will proceed and insert new values into pairVector which is guaranteed to have enough space.
A couple of other things are possible. Since you have stated that both vectors will always have the same size, you only need to check the size of one of them:
for (int i = 0; i < strVector.size(); ++i )
Next step: at() performs bounds checking. This loop ensures that i will never be out of bounds, so at()'s bound checking is also some overhead you can get rid of safely:
pairVector.push_back(pair<string, int> (strVector[i], intVector[i]));
Next: with a modern C++ compiler, the compiler should be able to optimize away, automatically, several redundant temporaries, and temporary copies here. It's possible you may need to help the compiler, a little bit, and use emplace_back() instead of push_back() (assuming C++11, or later):
pairVector.emplace_back(strVector[i], intVector[i]);
Going back to the loop condition, strVector.size() gets evaluated on each iteration of the loop. It's very likely that a modern C++ compiler will optimize it away, but just in case you can also help your compiler check the vector's size() only once:
int i=strVector.size();
for (int i = 0; i < n; ++i )
This is really a stretch, but it might eke out a few extra quantums of execution time. And that pretty much all obvious optimizations here. Realistically, the most to be gained here is by using reserve(). The other optimizations might help things a little bit more, but it all boils down to moving a certain number of bytes from one area in memory to another area. There aren't really special ways of doing that, that's faster than other ways.
We can use std:generate() to achieve this:
#include <bits/stdc++.h>
using namespace std;
vector <string> strVector{ "hello", "world" };
vector <int> intVector{ 2, 3 };
pair<string, int> f()
{
static int i = -1;
++i;
return make_pair(strVector[i], intVector[i]);
}
int main() {
int min_Size = min(strVector.size(), intVector.size());
vector< pair<string,int> > pairVector(min_Size);
generate(pairVector.begin(), pairVector.end(), f);
for( int i = 0 ; i < 2 ; i++ )
cout << pairVector[i].first <<" " << pairVector[i].second << endl;
}
I'll try and summarize what you want with some possible answers depending on your situation. You say you want a new vector that is essentially a zipped version of two other vectors which contain two heterogeneous types. Where you can access the two types as some sort of pair?
If you want to make this more efficient, you need to think about what you are using the new vector for? I can see three scenarios with what you are doing.
The new vector is a copy of your data so you can do stuff with it without affecting the original vectors. (ei you still need the original two vectors)
The new vector is now the storage mechanism for your data. (ei you
no longer need the original two vectors)
You are simply coupling the vectors together to make use and representation easier. (ei where they are stored doesn't actually matter)
1) Not much you can do aside from copying the data into your new vector. Explained more in Sam Varshavchik's answer.
3) You do something like Shakil's answer or here or some type of customized iterator.
2) Here you make some optimisations here where you do zero coping of the data with the use of a wrapper class. Note: A wrapper class works if you don't need to use the actual std::vector < std::pair > class. You can make a class where you move the data into it and create access operators for it. If you can do this, it also allows you to decompose the wrapper back into the original two vectors without copying. Something like this might suffice.
class StringIntContainer {
public:
StringIntContaint(std::vector<std::string>& _string_vec, std::vector<int>& _int_vec)
: string_vec_(std::move(_string_vec)), int_vec_(std::move(_int_vec))
{
assert(string_vec_.size() == int_vec_.size());
}
std::pair<std::string, int> operator[] (std::size_t _i) const
{
return std::make_pair(string_vec_[_i], int_vec_[_i]);
}
/* You may want methods that return reference to data so you can edit it*/
std::pair<std::vector<std::string>, std::vector<int>> Decompose()
{
return std::make_pair(std::move(string_vec_), std::move(int_vec_[_i])));
}
private:
std::vector<std::string> _string_vec_;
std::vector<int> int_vec_;
};
I need to init a 2-dim array of forward_list after I read its sizes from input.
class Foo{
forward_list<int> * koo;
int A, B;
void boo(){
scanf("%d",&A);
scanf("%d",&B);
koo = new forward_list<int>[A][B];
koo[0][0] = 1;
}
};
Compiler:
cannot convert ‘std::forward_list<int> (*)[1]’ to ‘std::forward_list<int>*’ in assignment adjList = new forward_list<int>[A][A];
CLion IDE: Subscribed value is not an array (at koo[0])
I don't do much C++ so I don't quite know what's wrong. How can I do this right? I need to access all forward_list in O(1), and would, therefore, prefer arrays or generally something fast.
Btw: not sure if this is called dynamic initialization, let me know if I should change the title.
Thanks.
A forward_list is incapable of reaching your performance requirement: "I need to access all forward_list in O(1)" you can see that in a comparision here: https://en.wikipedia.org/wiki/Linked_list#Linked_lists_vs._dynamic_arrays You can see that Indexing for a forward_list and other linked list variants is O(n).
The simplest container type that does provide the O(1) indexing you're looking for is a vector or another of the dynamic array variants. I believe your current needs could be satisfied by doing something like:
vector<vector<int>> koo(A, vector<int>(B));
It should be mentioned that while this will satisfy your performance requirements, a vector of vectors isn't a great solution; but you can look at it as a good stopgap solution.
I am new to stl and i came across a question where it is required to store a lot of pairs having same characteristics (like:- (string,int)) together. Can we store pairs in array and if so how? Thanks in advance..
You can try something like:
struct demo
{
string str;
int i;
};
std::array<demo, 5> arr; //for fixed size array of 5 elements
std::vector<demo> vec; //for dynamic size arrays
You want ...
to store a lot of pairs having same characteristics
The terminology is a bit wrong. You want to store many pairs of the same type (not "characteristics").
You could define your own struct as answered by Nipun, or use
std::array<std::pair<std::string,int>, 10> arr;
for an array of 10 pairs of strings and ints.
Spend more time on reading a documentation on standard containers and standard utilities. Perhaps you want some other existing thing (e.g. std::set with std::tuple, maybe with your own comparator).
Templates can (and often should) be combined since they are compositional. Be also aware of the rule of five.
I have an std::set of integers of say 550 elements. I want to split this into vectors of size 100 or less. So, lets say, in this case we will get 6 vectors in all. First 5 vectors will be of sizes 100 and the sixth vector will be of size 50.
So, effectively I need to break std::setmasterSet into std::vector>final. Is there a good and crisp way to do it using some standard std algorithms. I dont need a class to have this logic, infact I can write a function to do this.
Hmm...I guess you could do something on this general order:
std::vector<vector<int>> ints(myset.size()/max_size);
size_t i = 0;
for (auto d : my_set)
ints[i++/max_size].push_back(d);
I have been reading up on C++ lately, especially STL, and I decided to do the Knights Tour problem again. I'm thinking about the best way to implement this, and I'm looking for some help.
Just for fun and practice, I thought I'd start with a "Piece" base class, which a "Knight" class can inherit from. I want to do this so I later can try adding other pieces(even though most of the pieces can't walk over the whole board and complete the problem).
So the "piece class" will need some sort of container to store the coordinates of the piece on the board and the number of moves it has made in that specific step.
I'm thinking I need a linked list with 64 (8 * 8) places to do this most efficiently, containing x,y and moves.
Looking at the STL containers, I can't find anything except map that will hold more than one type.
What can I do to store the coordinate pair and an int for the number of moves in one container? Are there more efficient ways of doing this than using vector, list or map? Do I need a custom container?
Thanks!
You can use
struct CellInfo
{
int x, y, move_count;
}
And store it in std::vector for constant access.
Apart from STL and encapsulation, a very efficient way is to use arrays:
pair<int, int> piece_pos[N];
int piece_move[N];
This avoids the overhead of memory leakage and is faster than dynamic allocation.
If you stell want to use STL, then:
vector<pair<int, int> > piece_pos(N);
vector<int> piece(N);
The C++ STL now has static arrays as well. If you want to store the number of times a given x,y coordinate has been moved to, you can create an array of arrays like the following:
using container_type = std::array<std::array<int, 8>, 8>;
// ...
container_type c;
int moves = c[x][y]; // constant-time access.
If you don't need to look moves up based on x,y, and just want the data stored efficiently, use a flat array of size 8x8 = 64.
If your compiler is out of date, consider using std::vector instead.