-
December 2nd, 2012, 12:29 AM
#1
matrixarray
I wish to convert a 2D Array i.e int a[20][20] , convert to either s single array as in in[400] or hold it in a vector , and then back again , any ideas ?
my initial thoughts were
Code:
for(a to 200)
for(b to 200)
{
vector.push.back(int[a][b]); // this in sudo code ;
}
-
December 2nd, 2012, 02:57 AM
#2
Re: matrixarray
Originally Posted by aamir121a
I wish to convert a 2D Array i.e int a[20][20] , convert to either s single array as in in[400] or hold it in a vector , and then back again , any ideas ?
Code:
#include <algorithm>
#include <vector>
template <typename T>
struct VectorFrom2DArrayInitializer
{
typedef std::vector<T> TVector;
TVector & m_v;
int m_nElements;
VectorFrom2DArrayInitializer(TVector& theVector, int numElements) :
m_v(theVector), m_nElements(numElements) {}
void operator()(T *pElements)
{ m_v.insert(m_v.end(), pElements, pElements + m_nElements); }
};
template <typename T, int Rows, int Cols>
void Init1DVectorFrom2DArray(std::vector<T>& v, T arr[Rows][Cols])
{ std::for_each(arr, arr + Rows, VectorFrom2DArrayInitializer<T>(v, Cols)); }
int main()
{
// Initialize array to something
int a[20][20];
int counter = 0;
for (int i = 0; i < 20; ++i)
for (int j = 0; j < 20; ++j)
a[i][j] = counter++;
// set vector to the above array
std::vector<int> v;
Init1DVectorFrom2DArray<int, 20, 20>(v, a);
}
Well, this uses no loops except for the initializer for the array at the beginning of the test main() program.
It now doesn't matter if it's a 2d array of int, char, double, or Widgets. The 2d array of T is copied to the 1d vector of T using for_each() and a function object. Note that the only reliance on "int" is in the template argument to the Init1DVectorFrom2DArray function. Then everything there relies on type T, regardless of what T is.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; December 2nd, 2012 at 03:13 AM.
-
December 2nd, 2012, 07:14 AM
#3
Re: matrixarray
Originally Posted by aamir121a
, any ideas ?
Instead of copying the arrays you can "overlay" them using a union,
Code:
union Same {
int a[50];
int b[10][5];
};
Here a and b represent the same 50 consecutive ints of memory, only they are accessed according to different matrix abstractions (and more can be added).
Code:
Same same; // static allocation at compile time
//
same.b[2][3] = 42;
std::cout << same.a[13] << std::endl;
It works because b[2][3] and a[13] represent the same memory position (2*5 + 3 = 13).
Since std::vector allocates memory dynamically a pointer must be used in that case. The above becomes,
Code:
std::vector<int> v(50); // dynamic allocation at runtime
Same* same = reinterpret_cast<Same*>(&v[0]); // sets Same pointer to start of vector data
//
same->b[2][3] = 42;
std::cout << same->a[13] << std::endl;
std::cout << v[13] << std::endl;
Last edited by nuzzle; December 3rd, 2012 at 06:00 AM.
-
December 4th, 2012, 07:41 PM
#4
-
December 5th, 2012, 03:04 AM
#5
Re: matrixarray
Originally Posted by nuzzle
they are accessed according to different matrix abstractions (and more can be added).
I think this is not advisable; that use of unions relies on specific guarantees related to not-so-manifest properties of the types involved. Even with POD's you have to make sure that those member types have the same memory layout. Yes, with C++11 things have been relaxed to allow standard memory layout types with compatible layouts ( so, say, you could put there an std::array ) but it's still non trivial to check that the code is actually portable. So, I'd leave this technique to implementation details only.
-
December 5th, 2012, 07:19 AM
#6
Re: matrixarray
Originally Posted by superbonzo
So, I'd leave this technique to implementation details only.
With different matrix abstractions I meant variations of 50 consecutive ints, like say
Code:
union Same {
int a[50];
int b[10][5];
int c[25][2];
int d[2][5][5];
// etcetera
};
To the best of my knowledge my suggestion is portable according to the C++ 11 standard (both regarding memory layout and the use of the reinterpret_cast).
But I agree that C-ish stuff like this shouldn't be all over the place in a C++ program.
-
December 5th, 2012, 12:43 PM
#7
Re: matrixarray
alternatvively... "why does it matter" ?
The data will ultimately be stored similarly, why does your code need to make a difference between 2D (or xD for that matter) or flat (1D) ?
If you have a need for a container that allows your data to be approached "flat" as well as 2d or 3d, then why not simply make a container like that. Make a template class that takes 2 dimentions, use it to make a X*Y vector, then provide members that can access the data either flat (with 1 index) or as a 2D array (with 2 indexes) (or as a 3D, 4D..... whatever).
-
December 6th, 2012, 04:47 AM
#8
Re: matrixarray
Originally Posted by OReubens
If you have a need for a container that allows your data to be approached "flat" as well as 2d or 3d, then why not simply make a container like that.
Yes, that's the way I'd approach it.
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|