Pushing an array into a vector

2019-01-24 17:25发布

问题:

I've a 2d array, say A[2][3]={{1,2,3},{4,5,6}}; and I want to push it into a 2D vector(vector of vectors). I know you can use two for loops to push the elements one by on on to the first vector and then push that into the another vector which makes it 2d vector but I was wondering if there is any way in C++ to do this in a single loop. For example I want to do something like this:

myvector.pushback(A[1]+3); // where 3 is the size or number of columns in the array.

I understand this is not a correct code but I put this just for understanding purpose. Thanks

回答1:

The new C++0x standard defines initializer_lists which allows you to:

vector<vector<int>> myvector = {{1,2,3},{4,5,6}};

gcc 4.3+ and some other compilers have partial C++0x support. for gcc 4.3+ you could enable c++0x support by adding the flag -std=c++0x

Its not the best way to have your static data represented like that. However, if your compiler vendor supports C++ tr1 then you could do:

#include <tr1/array>  // or #include <array>
...

typedef vector<vector<int> > vector2d;
vector2d myvector;

// initialize the vectors
myvector.push_back(vector<int>());
myvector.push_back(vector<int>());

typedef std::array<std::array<int, 3>, 2> array2d;
array2d array = {{1,2,3},{4,5,6}};
array2d::const_iterator ai = array.begin(), ae = array.end();
for (vector2d::iterator i = myvector.begin(), e = myvector.end()
    ; i != e && ai != ae
    ; i++, a++)
{
    // reserve vector space
    i->reserve(array.size());

    // copy array content to vector
    std::copy(ai.begin(), ai->end(), i->begin());
}


回答2:

This is a little tricky, but you could use template recursion to help you in having the assignment done almost completely at compile-time. I understand that's not exactly what you are looking for, but I think it's worthwhile :-)

Here's the code:

#include <vector>

using namespace std;

typedef vector<vector<int> > vector2d;

template<size_t K, size_t M, size_t N>
struct v_copy {
    static void copy(vector2d& v, int(&a)[M][N])
    {
        v[K - 1].assign(a[K - 1], a[K - 1] + N);
        v_copy<K - 1, M, N>::copy(v, a);
    }
};

template<size_t M, size_t N>
struct v_copy<1, M, N> {
    static void copy(vector2d& v, int(&a)[M][N])
    {
        v[0].assign(a[0], a[0] + N);
    }
};

template<size_t M, size_t N>
void copy_2d(vector2d& v, int(&a)[M][N])
{
    v_copy<M, M, N>::copy(v, a);
}

int main()
{
    int A[2][3] = {{0, 1, 2}, {10, 11, 12}};
    vector2d vector(2);

    copy_2d(vector, A);
}

it needed a struct because in C++ you can't do partial specialization of functions. BTW , compiling it with gcc version 4.5.0, this code produces the same assembly as

vector[1].assign(A[1], A[1] + 3);
vector[0].assign(A[0], A[0] + 3);

It should not be very hard to have it compile with different types of 2-dimensions arrays.



回答3:

You can use vector::assign (pointers to array elements are valid iterators):

int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
std::vector<std::vector<int> > v(2);
for (size_t i = 0; i < 2; ++i)
   v[i].assign(a[i], a[i] + 3);


回答4:

If you want to push the data into vector of vectors, you have to write something like this:

vector<int> inner;
vector< vector<int> >outer;

...
outer.pushback(inner);

I think there is no way to do it in a single loop.

If you want to use just one vector (something similar like you written), then you can do it in a single loop:

int A[2][3]={{1,2,3},{4,5,6}};
int* p = A[0];
std::vector<int> inner;
std::vector< std::vector<int> >outer;

for(int i = 0; i < 6; ++i)
{
    inner.push_back(*p++);
}


回答5:

It's kind of cheating, but you could take advantage of the vector constructor to do one of the loops for you:

#include <vector>

int main() {
  const int XMAX = 2, YMAX = 3;
  int A[XMAX][YMAX] = {{1,2,3}, {4,5,6}};
  std::vector<std::vector<int> > v;

  for (size_t x = 0; x < XMAX; ++x) {
    v.push_back(std::vector<int>(&A[x][0], &A[x][YMAX]));
  }
}


回答6:

You can resize vectors and then use copy.

int A[2][3]={{1,2,3},{4,5,6}};
std::vector< std::vector<int> > vec;

vec.resize(2);
for (int i=0; i<2; i++)
{
    vec[i].resize(3);
    std::copy(A[i], A[i]+3, vec[i].begin());
}

Is it practical? Definetly not.



回答7:

Hm... I can produce a partial answer but not a full one.

int elementCount = 6; // I wonder if this can be done somehow with sizeof(A) * sizeof(A[0])
int* end = A + elementCount;
for(int* current = A; current < end; ++current) {
    myvector.pushback(*current);
}


回答8:

No. The only thing you can do is leverage existing loop functions so that you only have to write one or zero of your own loops.



标签: c++ vector