Juicy
Juicy

Reputation: 12520

Get sub array from a 3D array

If I have an array:

int[,,] mainArray = new int[10,10,3];

How can I get a sub array:

int[] sub = mainArray[0,1]; // Unfortunately this doesn't work

Where sub would contain the 3 elements

sub[0] = mainArray[0,1,0];
sub[1] = mainArray[0,1,1];
sub[2] = mainArray[0,1,2];

It would be easy to write a method to do this but is there a built in way to do it?

Upvotes: 7

Views: 796

Answers (3)

Daniel A.A. Pelsmaeker
Daniel A.A. Pelsmaeker

Reputation: 50326

You could use nested arrays instead.

// Initialization
int[][][] mainArray = new int[10][][];
for (int i = 0; i < mainArray.Length; i++)
{
    mainArray[i] = new int[10][];
    for (int j = 0; j < mainArray[i].Length; j++)
    {
        mainArray[i][j] = new int[3];
    }
}

// Usage
int[] sub = mainArray[0][1];

Yes, the initialization is a bit more complex, but other than that it's all the same. And nested arrays even have better performance (but you shouldn't care about array performance unless your profiler told you so).


Here is a helper class I wrote to help with the initialization of nested arrays.

public static class NestedArray
{
    public static Array Create<T>(params int[] lengths)
    {
        Type arrayType = typeof(T);
        for (int i = 0; i < lengths.Length - 1; i++)
            arrayType = arrayType.MakeArrayType();

        return CreateArray(arrayType, lengths[0], lengths.Skip(1).ToArray());
    }

    private static Array CreateArray(Type elementType, int length, params int[] subLengths)
    {
        Array array = Array.CreateInstance(elementType, length);

        if (subLengths.Length > 0)
        {
            for (int i = 0; i < length; i++)
            {
                Array nestedArray = CreateArray(elementType.GetElementType(), subLengths[0], subLengths.Skip(1).ToArray());
                array.SetValue(nestedArray, i);
            }
        }

        return array;
    }
}

Usage:

int[][][] mainArray = (int[][][])NestedArray.Create<int>(10, 10, 3);

Full commented source code can be found in this gist.

Upvotes: 2

trutheality
trutheality

Reputation: 23465

You can use Buffer.BlockCopy and some math, if you always want the the last dimension:

Buffer.BlockCopy(mainArray, (D2*i+j)*D3*sizeof(TYPE), sub, 0, D3*sizeof(TYPE));

will put mainArray[i,j,] in sub, where D1, D2, and D3 are your dimensions and TYPE is the type of the array elements.

Upvotes: 1

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101701

I think you can use an extension method like this:

public static class MyExtensions
{
    public static int[] GetValues(this Array source, int x, int y)
    {
        var length = source.GetUpperBound(2);
        var values = new int[length+1];
        for (int i = 0; i < length+1; i++)
        {
            values[i] = (int)source.GetValue(x, y, i);
        }
        return values;
    }
}

Usage:

int[,,] mainArray = new int[10,10,3];
int[] sub = mainArray.GetValues(0, 1);

Upvotes: 2

Related Questions