Pushing an array into a vector - c++

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

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());
}

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);

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.

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++);
}

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]));
}
}

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.

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);
}

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.

Related

How to push_back() C array into std::vector [duplicate]

This question already has answers here:
Correct way to work with vector of arrays
(4 answers)
Closed 2 years ago.
This doesn't compile:
vector<int[2]> v;
int p[2] = {1, 2};
v.push_back(p); //< compile error here
https://godbolt.org/z/Kabq8Y
What's the alternative? I don't want to use std::array.
The std::vector declaration on itself compiles. It's the push_back that doesn't compile.
You could use a structure containing an array, or a structure containing two integers, if you really don't want to use std::array:
struct coords {
int x, y;
};
vector<coords> v;
coords c = {1, 2};
v.push_back(c);
alternatively, as mentioned, you could use a structure containing an array:
struct coords {
int x[2];
};
vector<coords> v;
coords c = {1, 2};
v.push_back(c);
Use std::array:
vector<std::array<int, 2>> v;
std::array<int, 2> p = {1, 2};
v.push_back(p);
I think you should check the C++ reference for vectors.
http://www.cplusplus.com/reference/vector/vector/vector/
You can see in the example, there is explained every way you can initialize a vector.
I think that for your case you need to do:
std::vector<int> v({ 1, 2 });
v.push_back(3);
As an alternative, as you explicitly state that std::array is not to be used, you could use pointers, it's kind of an oddball solution but it would work:
#include <iostream>
#include <vector>
int main()
{
const int SIZE = 2;
std::vector<int*> v;
static int p[SIZE] = {1, 2}; //extended lifetime, static storage duration
int *ptr[SIZE]; //array of pointers, one for each member of the array
for(int i = 0; i < SIZE; i++){
ptr[i] = &p[i]; //assign pointers
}
v.push_back(*ptr); //insert pointer to the beginning of ptr
for(auto& n : v){
for(int i = 0; i < SIZE; i++){
std::cout << n[i] << " "; //output: 1 2
}
}
}

Passing two arrays as parameters and calculating the sum of them in c++

Write a function which will take two arrays as parameters and add the individual
elements of each array together such that firstArray[i] = firstArray[i] +
secondArray[i] where 0 <= i <= 4.
int[] sumEqualLengthArrays(int[] a, int[] b) {
int[] result = new int[a.length];
for (int i = 0; i < a.length; i++)
result[i] = a[i] + b[i];
return result;
}
I have been stuck on this for a while now and I just can't get my head around what the answer is. I have attempted to answer it in the code above. I am a beginner to C++ programming as I am studying it in my free time. An answer to this question would really help!
Since you said you can use anything, Use std::vector with std::transform and std::plus<int>(). something like this :
std::transform (a.begin(), a.end(), b.begin(), a.begin(), std::plus<int>());
If you insist on using normal arrays (here assume a and b are arrays) then you can do something like this :
std::transform(a, &a[number_of_elements], b, a, std::plus<int>());
But please, don't.. Use std::vector.
How to use first approach :
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> a = {1, 2, 3};
std::vector<int> b = {1, 2, 3};
std::transform(a.begin(), a.end(), b.begin(), a.begin(), std::plus<int>());
for(auto iter = a.begin(); iter != a.end(); ++iter)
{
std::cout << *iter << std::endl;
}
return 0;
}
How to use second approach :
#include <iostream>
#include <algorithm>
int main()
{
int a[3] = {1, 2, 3};
int b[3] = {1, 2, 3};
std::transform(a, &a[0] + 3, b, a, std::plus<int>());
for(int i = 0; i < 3; ++i)
{
std::cout << a[i] << std::endl;
}
return 0;
}
Something like this:
std::vector<int> sumEqualLengthArrays(const std::vector& rhs,
const std::vector& lhs){
if(lhs.length() == rhs.length()){
std::vector<int> result(rhs.length(), 0);
for(unsigned int i = 0; i < rhs.length; ++i){
result[i] = rhs[i] + lhs[i];
}
return result;
}else{
std::cout << "Length is not equal!" << std::endl;
return rhs;
}
}
I would advise to use vectors instead of arrays and check the length before usage just in case to avoid errors.
You've written the summing expression already in the problem formulation. If you look at it once again, you'll see that the result is stored in first and there's no need in separate result array (returning an array is not a trivial thing in C++).
And, speaking of which, passing arrays as arguments is not easy either.
Assuming, you don't use std::vector, simple options are as follows.
int a[] (note the position of square brackets) as a function formal argument is synonymous to a pointer. It does not contain any size information, so you'll have to add a third argument which is the minimal size of both arrays:
int *add(int a[], int b[], std::size_t commonSize) { // commonSize is the least of a's and b's sizes
for(std::size_t i = 0; i < commonSize; ++i) a[i] += b[i];
return a;
}
You can deduce array's size when passed by reference, this is allowed in C++ and is a serious deviation from classic C:
template<std::size_t A, std::size_t B> int (&add(int (&a)[A], int (&b)[B]))[A] {
for(std::size_t i = 0; i < std::min(A, B); ++i) a[i] += b[i];
return a;
}
Then the common size is the minimum of A and B.
You can use std::array, this is almost the same as previous option
template<std::size_t A, std::size_t B> void add(std::array<int, A> &a, std::array<int, B> const &b);
This way you can even use range-for loops, or, for instance, STL algorithms (which tend to acquire parallelized and non-sequential overloads recently), though it requires a small amount of additional work (which is a bit too large to fit in this margin).

Flatten n-dimensional vector

I worked out an algorithm that can be used recursively, which works in a non-recursive manner, however, I cannot test it in recursive form because I cannot create a n-1 dimensional variable from the template.For help I write down the variable names and its meaning:
v: the n-dimensional vector
dims: n long vector with every dimension (e.g: if it was an array looking like int x[3][6][4], then dims looks like: {3, 6, 4})
p: product of the dimensions, used to get the size of the flat vector (e.g: 3*6*4)
ret: the returned flat vector
sub_dims: same as dims execpt without the first dimension (e.g: {6, 4})
sub_p: same as p except without the first factor (e.g: 6*4)
sub_ret: the returned flat vector for the n-1 dimensional vector
the code:
template <typename T>
vector<int> dim_flat(vector<T> v, vector<int> dims)
{
// creating variables and vectors
int n = dims.size();
int p = dims[0];
for (int i = 1; i < n; i++)
{
p *= dims[i];
}
int sub_p = p / dims[0];
vector<int> sub_dims;
sub_dims.assign(dims.begin() + 1, dims.end());
vector<int> ret(p);
// algorithm
if (n > 1)
{
for (int i = 0; i < dims[0]; i++)
{
vector<int> sub_ret = dim_flat(v[i], sub_dims);
for (int j = 0; j < sub_p; j++)
{
ret[i * sub_p + j] = sub_ret[j];
}
}
}
else
{
// case for the input is 1D
// not yet written
}
return ret;
}
With this code the project build, however if I call it in main:
vector<int> ret = dim_flat(v, dims);
where v is e.g. an 4D vector and dims is a vector containing {3, 3, 3, 3}, then I get the following when trying to build:
error C2784: 'std::vector<_Ty> dim_flat(std::vector<T>,std::vector<_Ty>)' : could not deduce template argument for 'std::vector<T>' from 'int'
for the line
vector<int> sub_ret = dim_flat(v[i], sub_dims);
I kinda (but not really) understand the meaning of this error, so I expected the same to happen, which it did for this:
T x = v[i];
vector<int> sub_ret = dim_flat(x, sub_dims);
This is the part where I don't really understand the error anymore, because I thought that with the argument vector<T> v I specified that the input e.g. 4D vector will be understood as a vector of T where T is a 3D vector that can be also indexed since its a vector<T>. So following this logic I thought that if I give the recursion the first T being a 3D vector, then a step deeper this 3D vector will now be understood as a vector of T' where T' is a 2D vector, and so on.
Clearly either my logic is flawed, or I used the wrong method (, or both), so the question is: How can I solve / fix this?
EDIT:Credit to Max66 for the solution.
The code probably could be more optimized, but at least now it works.
Code:
//// for integer only
// case input is 0-dimensional (simply a variable)
template <typename T>
vector<int> dim_flat (const T &v, const vector<int> &dims)
{
return vector<int>(1, v);
}
// case input is n-dimensional
template <typename T>
vector<int> dim_flat(const vector<T> &v, const vector<int> &dims)
{
// creating variables and vectors
int n = dims.size();
int p = dims[0];
for (int i = 1; i < n; i++)
{
p *= dims[i];
}
int sub_p = p / dims[0];
vector<int> sub_dims;
sub_dims.assign(dims.begin() + 1, dims.end());
vector<int> ret(p);
// algorithm
if (n > 1) // case n-dimensional
{
for (int i = 0; i < dims[0]; i++)
{
vector<int> sub_ret = dim_flat(v[i], sub_dims);
for (int j = 0; j < sub_p; j++)
{
ret[i * sub_p + j] = sub_ret[j];
}
}
}
else // case 1-dimensional
{
for (int i = 0; i < p; i++)
{
vector<int> sub_ret = dim_flat(v[i], sub_dims);
ret[i] = sub_ret[0];
}
}
return ret;
}
Short answer: add the function
std::vector<int> dim_flat (int v, std::vector<int> const &)
{ return {v}; }
if you can use C++11 or newer, or
std::vector<int> dim_flat (int v, std::vector<int> const &)
{ return std::vector<int>(1, v); }
if you have to use C++98
Long answer: if I'm not wrong, the problem is that, when you call dim_flat() with an std::vector<int> (when T is int), you have n == 1, so dim_flat() isn't called (is executed the "case for the input 1D") but the compiler isn't so smart to understand that there is no need to call dim_flat() with int (instead std::vector<T>) so look for dim_flat(int, std::vector<int>) and doesn't find it.
So, to make the compiler happy, you have to implement dim_flat(int, std::vector<int>).
Can be a dummy function (that return an empty vector), but I suggest you to implement it correctly.
A little of topic: please, avoid unusefull copies of vectors; in your dim_flat(), v and dims are only readed, not modified; so you can receive they as const reference, as follows
template <typename T>
std::vector<int> dim_flat(std::vector<T> const & v,
std::vector<int> const & dims)
P.s.: why don't you simply write as follows ?
std::vector<int> dim_flat (std::vector<int> const & v)
{ return v; }
template <typename T>
std::vector<int> dim_flat(std::vector<std::vector<T>> const & v)
{
std::vector<int> ret;
for ( auto const & e : v )
{
auto s = dim_flat(e);
ret.reserve( ret.size() + s.size() );
ret.insert( ret.end(), s.cbegin(), s.cend() );
}
return ret;
}

Nice way to create a dynamic 2D matrix in C++ 11

I already know how to create a dynamic 2D matrix using new and free it using delete. Since C++ 11 is here with many new memory features such as unique_ptr, array container etc.; what is a nice way to create a 2D matrix so that one needs not to free the matrix explicitly using delete operator?
One of the simplest ways is to use a vector of vectors
const int N = 10;
const int M = 10;
vector<vector<int>> matrix2d(N, vector<int>(M, 0)); // 10x10 zero-initialized matrix
matrix2d[0][0] = 42;
You could of course use a single vector and wrap it into an accessor class
vector<int> matrix(N * M, 0) // Ditto as above, but needs stride-aware accessors
I'll post a small example here for completeness' sake
template <typename T>
class Matrix2D {
std::vector<T> data;
unsigned int sizeX, sizeY;
public:
Matrix2D (unsigned int x, unsigned int y)
: sizeX (x), sizeY (y) {
data.resize (sizeX*sizeY);
}
T& operator()(unsigned int x, unsigned int y) {
if (x >= sizeX || y>= sizeY)
throw std::out_of_range("OOB access"); // Throw something more appropriate
return data[sizeX*y + x]; // Stride-aware access
}
};
Live Example
or perhaps combine your way with a smart pointer. Notice that the vector<vector<int>> approach should be used with caution since the vectors are independent from each other and there's nothing to enforce that they should keep their size fixed.
I strongly suggest using array_view from the GSL, which will eventually be part of the standard.
#include <array>
#include <vector>
#include "array_view.h" // must be manually imported until standardization
int main()
{
std::array<int, 10> arr{}; // 10 ints on the stack
std::vector<int> vec{12}; // 12 ints on the heap
auto a = gsl::array_view<int, 2>{{2, 5}, arr}; // 2D, 2x5 matrix
auto b = gsl::array_view<int, 3>{{3, 2, 2}, vec}; // 3D, 3x2x2 matrix
auto c = gsl::array_view<int>{vec}; // 1D, spans from `begin()` to `end()`
a[{0,3}] += b[{0,1,1}] * -c[2]; // access syntax
}
N.B. array_view holds no control over the lifetime of the range it looks at. See here for full details.
Edit:
array_view is dead as it was becoming too complicated in handling multidimensional arrays with zero cost abstraction. You should instead use span from the GSL.
See this for more information about span.
Based on above answers, I have found a simple way to create matrices although not using C++11 features. Here is an illustration.
#include <iostream>
#include <vector>
using namespace std;
typedef vector<vector<int>> Matrix2D;
typedef vector<Matrix2D> Matrix3D;
Matrix2D my_arr;
int main()
{
const size_t N = 9;
for(unsigned s = 4; s <= N; s++)
{
my_arr.resize(s);
for(unsigned i = 0; i < s; i++)
my_arr[i].resize(s,s);
for(unsigned i = 0; i < s; i++)
{
for(unsigned j = 0; j < s; j++)
cout << my_arr[i][j] << " ";
cout << endl;
}
cout << "\n\n";
}
return 0;
}

Crafting a custom call to inner_product (C++ STL)

I'm having trouble getting my head around how to use inner_product to combine a std::vector<float> and a std::vector<std::vector<float>>. Given, e.g., <2,3> and <<4,5>,<6,7>>, I'd like inner_product to produce
2*<4,5> + 3*<6,7> = <8,10> + <18,21> = <26,31>.
Supposing
vector<float> foo;
and
vector<vector<float>> bar;
are initialized and are of equal size, I don't know what UK1, UK2, and UK3 in
vector<float> ip =
inner_product(foo.begin(), foo.end(), bar.begin(), UK1, UK2, UK3);
should be. I suspect UK1 should be a vector filled with 0.0fs, of the same size as the vectors in bar. UK3 should perhaps be something like
std::transform(UK4.begin(), UK4.end(), UK4.begin(),
std::bind1st(std::multiplies<float>(), UK5));
And I guess UK2 should somehow represent component-wise vector<float> addition!
I don't even want to think about how much more complex this will become when the vectors in bar are replaced by objects of a class with float attributes...
Define the add and multiply functions like this:
static vector<float> add(const vector<float> &a,const vector<float> &b)
{
assert(a.size()==b.size());
size_t n = a.size();
vector<float> result(n);
for (size_t i=0; i!=n; ++i) {
result[i] = a[i]+b[i];
}
return result;
}
static vector<float> mul(const float &a,const vector<float> &b)
{
size_t n = b.size();
vector<float> result = b;
for (size_t i=0; i!=n; ++i) {
result[i] *= a;
}
return result;
}
And use it like this:
vector<float> zero(2,0);
vector<float> result =
inner_product(a.begin(),a.end(),b.begin(),zero,add,mul);
std::inner_product accumulates a sum. UK2 is the sum operation. UK1 is normally the neutral element of UK2. UK3 is the multiplication operation that multiplies corresponding elements of the two sequences and returns a summand for UK2.
I guess std::valarray should provide a more suitable container for this operation.
// this is c++11
#include <vector>
#include <valarray>
#include <algorithm>
#include <iostream>
int main ()
{
std::valarray <int> zero = { 0, 0 };
std::vector <int> foo = { 1, 2, 3 };
std::vector <std::valarray<int>> bar = { { 3, 4 }, { 5, 6 }, { 7, 8 } };
std::valarray<int> result = std::inner_product (foo.begin(), foo.end(),
bar.begin(), zero);
for(auto n : result) {
std::cout << n << ' ';
}
std::cout << std::endl;
}