Reset vector of vector (2D array) to zero - c++

I am using vector of vector to simulate a 2D array. In order to reuse this 2D array, sometimes I need to reset all its elements to zero or some default value. I know for a simple 1D vector I can do:
std::fill(v.begin(), v.end(), 0);
How to do that efficiently for a vector<vector<int>>? I hope to find a solution without using for loops but more akin to some memset variant. I also don't want to incur any memory allocation and deallocation since my intent was to reuse the existing allocated memory.
Note that I am assuming each vector's size is fixed and known to me: vector<vector<int>> v(const_max_size, vector<int> (const_max_size, 0));. How to reset v's elements to zero?
NOTE: What I mean by not using for loops is that I don't want to iterate over all the 2D elements using subscripts like v[i][j] to assign them the value.

I hope to find a solution without using for loops ...
Well, either you do a loop explicitly or use something that loops implicitly. Nothing wrong with explicit loops:
for (auto& sub : v) {
std::fill(sub.begin(), sub.end(), 0);
}
I guess technically if you want to avoid a loop you could use:
std::for_each(v.begin(), v.end(),
[](auto& sub) {
std::fill(sub.begin(), sub.end(), 0);
});

I know I am going to get flack for this answer, but I am sure there is nothing faster:
for(auto& x : v) memset(&x[0],0,sizeof(int)*x.size());
memset is highly optimized for setting to 0.

Related

C++ efficient way to remove first x elements, push the x+1th element to the first without changing vector size

I'm wondering what's the most efficient(fastest, since the vector is not that big I don't care about memory usage) way to do this below:
Without changing vector size,
remove first x elements of the vector, push the rest of element to the first and assign new values to the last x elements. I guess vector::erase and ::push_back is probably not very fast since it change the size of the vector twice.
or is it better to give up vector and use arrays? Thanks.
vector::erase() doesn't reallocate, it only moves contents within the already-allocated capacity and adjusts the size. (Note that erase() doesn't throw bad_alloc, only copy/move/assignment exceptions. EDIT: That's not really relevant to this scenario.)
So calling erase() should be no less efficient than calling rotate().
erase() is probably more efficient, in fact, since rotate() not only moves the data that in your particular case you want to preserve, but also the data you're about to throw away - but which the semantics of rotate() dictate must also be preserved (which in turn probably necessitates either temporary storage or one-by-one movement). You can hope the optimiser manages to deal with this, or you can call erase().
Of course, the only real way to tell is to implement, measure, and compare.
So, based on your comment and as suggested by #Some programmer dude, this could do what you need:
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> vec{1,2,3,4,5,6,7,8};
const size_t X = 3;
std::rotate(vec.begin(), vec.begin() + X, vec.end());
std::transform(vec.end() - X, vec.end(), vec.end() - X, [](auto elem) {return elem += 10; });
}
Demo

using std::fill on a 2D int vector

I am trying to set the values of all elements in 2D vector to a particular value. As far as I am aware of, one cannot use memset for vectors like how they are used for arrays. Hence I have to use std::fill to set all elements in 2D vector to a particular value. However, I am aware of how to use fill for a 1D vector as show below.
vector<int> linearVector (1000,0);
fill(linearVector.begin(),linearVector.end(),10);
However, when I try to do something similar for a 2D vector(as shown below) it does not work.
vector<vector<int> > twoDVector (100,vector <int> (100,0));
fill(twoDVector.begin(),twoDVector.end(),10);
PS: I am aware that I can easily design a nested for loop to manually set the elements of the 2D vector to the value I want. However, It is not feasible in my program as the size of the 2D vector is quite large and there are other time consuming functions(recursive functions) happening in parallel.
In C++17 you can do it as below:
#include <algorithm>
#include <execution>
#include <vector>
//...
std::for_each(std::execution::par_unseq, nums.begin(), nums.end(),
[](std::vector<int>& vec) {
std::for_each(std::execution::par_unseq, vec.begin(), vec.end(),
[](int& n) {n = 10;});}
);
It seems to be parallel, but not as clear as simple fill function ;)
Of course you can pass your own variable instead of hardcoded 10.
This should help you
std::vector<std::vector<int> > fog(
A_NUMBER,
std::vector<int>(OTHER_NUMBER)); // Defaults to zero initial value
Reference: Initializing a two dimensional std::vector
You could use like this:
fill(twoDVector.begin(), twoDVector.end(), vector<int>(100, 10));

Most efficient way to clear array of vectors

I have a graph representation which looks like this
vector<int> Graph[MAXN]
Next, I want to remove all previously set vectors. What is the fastest way to do it ?
There's no real question of "efficiency" here. You must iterate through your array, and you must invoke std::vector<int>::clear() on each element of that array. So, just do it:
for (auto& v : Graph) {
v.clear();
}

push_back/append or appending a vector with a loop in C++ Armadillo

I would like to create a vector (arma::uvec) of integers - I do not ex ante know the size of the vector. I could not find approptiate function in Armadillo documentation, but moreover I was not successfull with creating the vector by a loop. I think the issue is initializing the vector or in keeping track of its length.
arma::uvec foo(arma::vec x){
arma::uvec vect;
int nn=x.size();
vect(0)=1;
int ind=0;
for (int i=0; i<nn; i++){
if ((x(i)>0)){
ind=ind+1;
vect(ind)=i;
}
}
return vect;
}
The error message is: Error: Mat::operator(): index out of bounds.
I would not want to assign 1 to the first element of the vector, but could live with that if necessary.
PS: I would really like to know how to obtain the vector of unknown length by appending, so that I could use it even in more general cases.
Repeatedly appending elements to a vector is a really bad idea from a performance point of view, as it can cause repeated memory reallocations and copies.
There are two main solutions to that.
Set the size of the vector to the theoretical maximum length of your operation (nn in this case), and then use a loop to set some of the values in the vector. You will need to keep a separate counter for the number of set elements in the vector so far. After the loop, take a subvector of the vector, using the .head() function. The advantage here is that there will be only one copy.
An alternative solution is to use two loops, to reduce memory usage. In the first loop work out the final length of the vector. Then set the size of the vector to the final length. In the second loop set the elements in the vector. Obviously using two loops is less efficient than one loop, but it's likely that this is still going to be much faster than appending.
If you still want to be a lazy coder and inefficiently append elements, use the .insert_rows() function.
As a sidenote, your foo(arma::vec x) is already making an unnecessary copy the input vector. Arguments in C++ are by default passed by value, which basically means C++ will make a copy of x before running your function. To avoid this unnecessary copy, change your function to foo(const arma::vec& x), which means take a constant reference to x. The & is critical here.
In addition to mtall's answer, which i agree with,
for a case in which performance wasn't needed i used this:
void uvec_push(arma::uvec & v, unsigned int value) {
arma::uvec av(1);
av.at(0) = value;
v.insert_rows(v.n_rows, av.row(0));
}

Swap columns in c++

I have an std matrix defined as:
std::vector<std::vector<double> > Qe(6,std::vector<double>(6));
and a vector v that is:
v{0, 1, 3, 2, 4, 5};
I would like to swap the columns 3 and 2 of matrix Qe like indicated in vector v.
In Matlab this is as easy as writing Qe=Qe(:,v);
I wonder if there is an easy way other than a for loop to do this in c++.
Thanks in advance.
Given that you've implemented this as a vector of vectors, you can use a simple swap:
std::swap(Qe[2], Qe[3]);
This should have constant complexity. Of course, this will depend on whether you're treating your data as column-major or row-major. If you're going to be swapping columns often, however, you'll want to arrange the data to suit that (i.e., to allow the code above to work).
As far as doing the job without a for loop when you're using row-major ordering (the usual for C++), you can technically eliminate the for loop (at least from your source code) by using a standard algorithm instead:
std::for_each(Qe.begin(), Qe.end(), [](std::vector<double> &v) {std::swap(v[2], v[3]); });
This doesn't really change what's actually happening though--it just hides the for loop itself inside a standard algorithm. In this case, I'd probably prefer a range-based for loop:
for (auto &v : Qe)
std::swap(v[2], v[3]);
...but I've never been particularly fond of std::for_each, and when C++11 added range-based for loops, I think that was a superior alternative to the vast majority of cases where std::for_each might previously have been a reasonable possibility (IOW, I've never seen much use for std::for_each, and see almost none now).
Depends on how you implement your matrix.
If you have a vector of columns, you can swap the column references. O(1)
If you have a vector of rows, you need to swap the elements inside each row using a for loop. O(n)
std::vector<std::vector<double>> can be used as a matrix but you also need to define for yourself whether it is a vector of columns or vector of rows.
You can create a function for this so you don't write a for loop each time. For example, you can write a function which receives a matrix which is a vector of columns and a reordering vector (like v) and based on the reordering vector you create a new matrix.
//untested code and inefficient, just an example:
vector<vector<double>> ReorderColumns(vector<vector<double>> A, vector<int> order)
{
vector<vector<double>> B;
for (int i=0; i<order.size(); i++)
{
B[i] = A[order[i]];
}
return B;
}
Edit: If you want to do linear algebra there are libraries that can help you, you don't need to write everything yourself. There are math libraries for other purposes too.
If you are in a row scenario. The following would probably work:
// To be tested
std::vector<std::vector<double> >::iterator it;
for (it = Qe.begin(); it != Qe.end(); ++it)
{
std::swap((it->second)[2], (it->second)[3]);
}
In this scenario I don't see any other solution that would avoid doing a loop O(n).