10

I find myself converting 1D byte and single arrays to 2D by doing the following. I suspect it is probably as fast as other methods, but perhaps there is a cleaner simpler paradigm? (Linq?)

    private static byte[,] byte2D(byte[] input, int height, int width)
    {
        byte[,] output = new byte[height, width];
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                output[i, j] = input[i * width + j];
            }
        }
        return output;
    }

    private static Single[,] single2D(byte[] input, int height, int width)
    {
        Single[,] output = new Single[height, width];
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                output[i, j] = (Single)input[i * width + j];
            }
        }
        return output;
    }
Dr.YSG
  • 7,171
  • 22
  • 81
  • 139

4 Answers4

13

This doesn't help with making the code inside the methods cleaner, but I noticed that you have 2 basically identical methods that differ only in their types. I suggest using generics.

This would let you define your method only once. Using the where keyword, you can even limit the kind of types you allow your method to work on.

private static T[,] Make2DArray<T>(T[] input, int height, int width)
{
    T[,] output = new T[height, width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            output[i, j] = input[i * width + j];
        }
    }
    return output;
}

You would call this method like this

int[] a;  //or any other array.
var twoDArray = Make2DArray(a, height, width);
ryanyuyu
  • 6,366
  • 10
  • 48
  • 53
5

Buffer.BlockCopy(input, 0, output, 0, input.Length); is faster, but fastest is to not copy the array at all.

If you don't really need a separate 2D array, you can just access your 1D array like a 2D array trough a function, property, or custom type. For example:

class D2<T> {
    T[] input;
    int lenght0;
    public d2(T[] input, int lenght0) {
        this.input = input;
        this.lenght0 = lenght0;
    }
    public T this[int index0, int index1] {
        get { return input[index0 * this.lenght0 + index1]; }
        set { input[index0 * this.lenght0 + index1] = value; }
    }
}

...

byte[] input = { 1, 2, 3, 4 };
var output = new D2<byte>(input, 2);
output[1, 1] = 0;  // now input is { 1, 2, 3, 0 };

Also, in .NET access to multidimensional arrays is a bit slower than access to jagged arrays

Slai
  • 22,144
  • 5
  • 45
  • 53
1

Generic function:

private static b[,] to2D<a, b>(a source, valueAt: Func<a, int, b>, int height, int width)
{
    var result = new b[height, width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            result[i, j] = valueAt(source, i * width + j);
        }
    }
    return result;
}

var bytes = to2D<byte[], byte>([], (bytes, at) => bytes[at], 10, 20);
Trident D'Gao
  • 18,973
  • 19
  • 95
  • 159
1

I know I am late to the party, but if you want to access a 1d array, list, etc. like it were an n-dimensional array (without copying) you can use https://github.com/henon/SliceAndDice to do so without copying.

// create a 2D array of bytes from a byte[]
var a = new ArraySlice<byte>( new byte[100], new Shape(10,10));
// now access with 2d coordinates
a[7,9]=(byte)56;

Of course, everyone can do it for simple 2d, 3d, ... nd volumes easily. But this lib also allows to do slicing of n-dimensional arrays without copying.

henon
  • 2,022
  • 21
  • 23