3

I'm just wondering whether there is a simple, quick way to insert the elements of a vector of vectors inside a vector.

For example:

std::vector<std::vector<double> > vals
{

    {1, 2, 3, 4, 5, 6},
    {1, 2, 3, 4, 5, 6}
};
std::vector<double> myvector;

so myvector would then contain: 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6

I've tried using insert and push_back but had no luck.

Edit:

I have used:

myvector.insert(vals.begin(), vals.end()); - No matching member function to call to 'insert'

Pat. ANDRIA
  • 2,330
  • 1
  • 13
  • 27
Phorce
  • 4,424
  • 13
  • 57
  • 107
  • 2
    Please show the exact code you used. – RedX Sep 18 '13 at 14:43
  • 1
    One would think that two normal [`insert`](http://en.cppreference.com/w/cpp/container/vector/insert) would be all it takes. – Some programmer dude Sep 18 '13 at 14:47
  • 1
    I think you mean that you want the elements of the vectors _inside_ the vector-of-vectors to be inserted into the other vector, correct? Please re-word if so. – davmac Sep 18 '13 at 14:47
  • @davmac Yes, but, I would like them to be inserted into a just a `vector` I do not need another `std::vector >` – Phorce Sep 18 '13 at 14:48
  • Right, then you need to clarify that in the question. You say 'insert the elements of a vector of vectors' but those would be vectors. You mean the elements _inside_ those vectors. – davmac Sep 18 '13 at 14:49

5 Answers5

10

Try

// c++11
for(auto && v : vals){
  myvector.insert(myvector.end(), v.begin(), v.end());
}

// non c++11
for(std::vector<std::vector<double> >::const_iterator it = vals.begin(), end = vals.end(); it != end; ++it){
  myvector.insert(myvector.end(), it->begin(), it->end());
}
RedX
  • 14,749
  • 1
  • 53
  • 76
  • 1
    A normal reference for first would be quite enough. – Some programmer dude Sep 18 '13 at 14:49
  • @RedX - `no matching member function for call to 'insert'` Any ideas why? – Phorce Sep 18 '13 at 14:50
  • a simple optimization here, would be to resize myvector first. This prevents unnecessary reallocations. – Enigma Sep 18 '13 at 14:50
  • @JoachimPileborg I remember reading somewhere that if the compiler thinks that a reference is enough here, with `&&` it will use that anyway. If it thinks that moving is also good, it might use that then. Or am i mistaken? – RedX Sep 18 '13 at 14:53
  • the inner loop shoud be myvector.insert(myvector.end(), v.begin(), v.end()) – Enigma Sep 18 '13 at 14:53
  • @Enigma You would have to iterate over all vectors anyway to find out if they are the same length anyway. I'm unsure if `insert` would not do a `std::difference` anyway if the iterators allows it and preallocate. – RedX Sep 18 '13 at 14:54
  • Also, you can't use `vals::const_iterator`, you need to use the complete type instead of the variable for scope. – Some programmer dude Sep 18 '13 at 14:54
  • @RedX: Yes but it potentially does a reallocate every vector – Enigma Sep 18 '13 at 14:54
  • @JoachimPileborg Thanks, was just too lazy to type it out. Fixed it now. – RedX Sep 18 '13 at 14:55
  • `auto&&` does not move. You're just binding a reference to an object. – fredoverflow Sep 18 '13 at 19:14
2

Depending on how your vector of vectors is built in the first place, there may be a more efficient way to approach this.

If your sub-vectors are all the same length (as appears to be the case from the code example), then the best thing may be to view myvector as a 2D array and build directly into this buffer.

If the sub-vector lengths can vary, but the code that builds your vector of vectors only ever actually adds stuff at the end, then you can use something like the 'collapsed vector vector' class I describe here to build this data, instead of a vector of vectors. (And after that, again, your data is already in the kind of contiguous buffer you are looking for.)

Either way, if performance or memory footprint are important here then avoiding the vector of vector construct can eliminate a lot of buffer manipulation overhead, and work out as quite a significant optimisation.

Thomas Young
  • 193
  • 3
  • 9
1

If you want to insert all of the elements of vals into a single vector:

Brute Force Method

for (int i = 0; i < vals.size(); ++i)
{
    for (int j = 0; j < vals[i].size(); ++j)
    {
        myvector.push_back(vals[i][j]);
    }
}

More Elegant Method

struct AddVector
{
    std::vector<double> myvector;
    void operator()(const std::vector<int>& a)
    {
        std::copy(a.begin(), a.end(), std::back_inserter(myvector));
    }
};

// somewhere in your code
AddVector av;
std::for_each(vals.begin(), vals.end(), av);
myvector.swap(av.myvector);
Zac Howland
  • 15,777
  • 1
  • 26
  • 42
0

The variable vals is a vector of vectors, but myvector is a vector of doubles. Trying to insert from the first into the second will not work as the contained types are different (std::vector<double> versus double).

Instead you have to manually insert from each sub-vector of vals into myvector.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

resize myvector to the size of the sum of the sizes of the vectors in vals. For every vector in vals concat it to myvector. To get a idea how to concat:

Concatenating two std::vectors

Community
  • 1
  • 1
Enigma
  • 1,699
  • 10
  • 14