Rasmus Damgaard Nielsen Rasmus Damgaard Nielsen - 3 months ago 20
C++ Question

Generic method for flattening 2d vectors

I have a function to flatten out an vector of vectors to a single vector. Comming from c# i would write it something like:

vector<T> flatten(vector<vector<T>> 2dVector)
{
vector<T> newVector(2dVector.size()*2dVector[0].size())
for (int i = 0; i < 2dVector.size(); i++)
{
for (int j = 0; j < 2dVector[i].size(); j++)
{
newVector[j + i * 2dVector.size()] = 2dVector[i][j];
}
}
return newVector;
}


but this code gives 20+ errors in msvc++

After hours of seaching the web for how to make this function, i modified the method signature to

utilities.h:

template <typename A, typename B> A flatten(const B 2dVector&);


utilities.cpp:

template <typename A, typename B> A flatten(const B 2dVector&)
{
A newVector(2dVector.size()*2dVector[0].size())
for (int i = 0; i < 2dVector.size(); i++)
{
for (int j = 0; j < 2dVector[i].size(); j++)
{
newVector[j + i * 2dVector.size()] = 2dVector[i][j];
}
}
return newVector;
}


But i still get on the order of ~15 errors from this code, and i am all out of ideas. Any suggestions?

Answer

Your code contains several problems. To name a few:

  1. An identifier cannot start with a number.
  2. Your template should be parameterized by a single parameter - the basic value type of the returned vector
  3. Your code internally assumes that the vectors are same-sized, where it is just as easy to accommodate a ragged array
  4. There are more efficient ways to append a vector to the end of a vector.

I'd suggest the following alternative:

#include <vector>

template<typename T>
std::vector<T> flatten(const std::vector<std::vector<T>> &orig)
{   
    std::vector<T> ret;
    for(const auto &v: orig)
        ret.insert(ret.end(), v.begin(), v.end());                                                                                         
    return ret;
}   

int main() 
{   
    std::vector<std::vector<int>> vv; 
    vv.push_back(std::vector<int>{1, 2, 3});
    vv.push_back(std::vector<int>{10, 20});
    flatten(vv);
}   
Comments