I have a 2D std::vector < std::vector <double> >
array consisting of three rows and an unknown number of columns. I would like to delete any column where the value of row 0 > row 1
. Here is my effort:
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array) {
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{1,1,2,1},{2,2,1,2},{3,3,3,3}};
printArray(fog);
for (int i = 0; i < fog[0].size(); ++i) {
for (int j = 0; j < fog.size(); ++j) {
if (fog[0][i] > fog[1][i]) {
fog[j].erase(fog[j].begin() + i);
}
}
}
printArray(fog);
The array is initially:
1 1 2 1
2 2 1 2
3 3 3 3
I would like it to become:
1 1 1
2 2 2
3 3 3
Instead I get:
1 1 1
2 2 1 2
3 3 3 3
I imagine the problem is because the size of the array is changing as elements are deleted, invalidating the loop conditions, and/or iterators are being removed. But with this observation, I have reach my (rather circumscribed) limits.
I would be most grateful for any advice.
The following approach deletes the desired columns "in place" instead of copying. The strategy is adapted from How to delete column in 2d vector, c++
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array) {
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{2,1,1,2,1,2,1,2,1,2},{1,2,2,1,2,1,2,1,2,1},{3,3,3,3,3,3,3,3,3,3}};
printArray(fog);
for (int i = 0; i < fog[0].size(); ++i)
{
if (fog[0][i] > fog[1][i]) {
/* // Alternative
std::for_each(fog.begin(), fog.end(), [&](std::vector<int>& row) {
row.erase(std::next(row.begin(), i));
});
*/
for(auto& row:fog) row.erase(std::next(row.begin(), i));
// accounts for deleted column
--i;
}
}
printArray(fog);
}
fog before loop is:
2 1 1 2 1 2 1 2 1 2
1 2 2 1 2 1 2 1 2 1
3 3 3 3 3 3 3 3 3 3
And fog after loop is:
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
Perhaps surprisingly, deleting in place did not speed up the operation compared to the copy approach used by me (@Bob) above. Maybe the amount of memory jockeying ends up being similar in both approaches. However, since there is no copying with the deleting in place strategy, it is presumably more efficient in terms of memory footprint.