简体   繁体   中英

Map 2D array into 1D array

For fun, I am trying to represent a 2D array in 1D array. How can I map a 2-dimensional array to 1 dimensional array?

For example, suppose we are given an array:

char[][] 2dArray = new char[4][4];

In 2-dimensional space, the range (0,0),(2,2) would represent 9 elements (represented as O below): O, O, O, XO, O, O, XO, O, O, XX, X, X, X

If we represent the two-dimensional array as a 1-dimensional array:

char[] 1dArray = new char[16];

it would look like this:

O, O, O, X, O, O, O, X, O, O, O, X, X, X, X, X

I already know that I can find the index of a single point in my 1-dimensional array via the formula: (rows * x + y) .

ie the 2d point (2,3) would map to the 1d index 11 in the given example.

Given a pair of 2D coordinates, How can I map a rectangular section of points to a 1D array? I prefer not to use loop nesting, if possible.

Let assume rectangular 2D array of chars like these:

const int xs=6; // columns
const int ys=4; // rows
char dat2D_xy[xs][ys]=
    {
    "06ci",
    "17dj",
    "28ek",
    "39fl",
    "4agm",
    "5bhn",
    };
char dat2D_yx[ys][xs]=
    {
    "012345",
    "6789ab",
    "cdefgh",
    "ijklmn",
    };
dat2D_xy[5][3] == dat2D_yx[3][5] == 'n';

Then to convert x,y coordinates to 1D index and back you can use:

i=x+(xs*y);
x=i%xs;
y=i/xs;

Or this:

i=y+(ys*x);
x=i%ys;
y=i/ys;

Does not matter which it just changes the order of items in the 1D array. To copy whole array to 1D you need to use 2 nested loops or just single one with addition to DMA or any other memory transfer. Something like this:

int i,x,y;
char dat1D[xs*ys];
for (i=0,y=0;y<ys;y++)
 for (x=0;x<xs;x++,i++)
  dat1D[i]=dat2D_xy[x][y];
//dat1D[i]=dat2D_yx[y][x];

//dat1D[]="0123456789abcdefghijklmn";

or:

int i,x,y;
for (i=0,x=0;x<xs;x++)
 for (y=0;y<ys;y++,i++)
  dat1D[i]=dat2D_xy[x][y];
//dat1D[i]=dat2D_yx[y][x];

//dat1D[]="06ci17dj28ek39fl4agm5bhn";

There are no X needed ... unless you want to add also the null termination characters at the end of each row/line to ease up debug view or process rows or columns as strings. In such case you add +1 for line size and add your termination character.

It is easy, first decide for a storage order (column major or row major), then with a nested loop you fill from 2D matrix A the 1D array B :

Example:

A is a NxM matrix

for i in 
    for j in M
        B[i*M + j] = A[i][j]

I think you will need some language features if you don't want neseted loop. This is my example in python.

First lets create a list a of dimension 4 x 4 where a[i][j] is a tuple of (i, j)

a = [[(i, j) for j in range(4)]for i in range(4)]

Now suppose we only want the submatrix from (1, 1) to (2, 3) . First lets filter elements from row 1 to row 2

rows = a[1:3]

Then we get the elements between col 1 and col 3 to get the submatrix.

submatrix = [row[1:4] for row in rows]

Now we have the submatrix, to convert it to 1d list, we can use sum

ans = sum(submatrix, [])

Finally if we print ans , we will have

[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)]

Combining things together, we have this function, where a is the input matrix, p1 and p2 are input points for locating the submatrix

def f(a, p1, p2):
    x1, y1 = p1
    x2, y2 = p2

    return sum([row[y1:y2 + 1] for row in a[x1:x2 + 1]], [])

It is possible without nested loop and no language support (and wasn't mentioned yet), but I doubt it will be faster (array with n rows and m columns):

for (int i = 0; i < n * m; i++)
    arr1D[i] = arr2D[i / m][i % m];

The modulo obviously gives 0, 1, 2, ..., m - 1 and then starts at 0 again, as it should and the result of the integer division is increased by one after a row is full. Or to read column by column (worse in most languages, better read row by row as above):

for (int i = 0; i < n * m; i++)
    arr1D[i] = arr2D[i % n][i / n];    

However this works only with rectangular matrices. Counter example:

int[][] arr2D = new int[2][];
arr2D[0] = new int[1];
arr2D[1] = new int[2];

In this case it would be best to do it in the standard way, using a list here because I don't know what the length of the result is going to be (add null checks if null is a possibility):

List<Integer> list = new ArrayList<>();
for (int i = 0; i < arr2D.lengh; i++)
    for (int j = 0; j < arr2D[i].length; j++)
        list.add(arr2D[i][j]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM