1

I have a multi-dimensional Array with unknown dimensions at compile time but at runtime (when i receive such Array) its dimension are described int[] dimensions. The length of dimensions is equal to the Rank of the Array and each element of dimensions contains the length of the relevant dimension.

What i want to obtain is a similar Array whose elements are mapped in a new object with a different type. I thought that LINQ could be useful so i wrote the following:

Array arr = ... //My multi-dimensional Array
var dimensions = ... //array describing the dimensions of arr. (NOT USED in the following but is an information i have)

var transformedArr = arr.Cast<StatusCode>().Select(val => JObject.FromObject(val)).ToArray();

It works but transformedArr is just a one-dimension Array now, hence i lost my multi-dimensional matrix. Have you got any idea to obtain a same Array with different element type only?

Please, note that i don't know a priori the dimensions of the array, only at runtime. In other words i can't use loops for indexing the multi-dimensional Array.

Any idea will be appreciated :)

2 Answers 2

1

I think following function should meet your requirements

public static void RecursiveCopy<TInput, TOutput>(
    Array source,
    Array destination,
    int[] dimensions,
    Func<TInput, TOutput> mutate,
    int[] indexPrefix = null)
{
    indexPrefix = indexPrefix ?? new int[0];
    if (dimensions.Length != 1)
    {
        for (var i = 0; i < dimensions[0]; i++)
        {
            var newDimensions = new int[dimensions.Length - 1];
            Array.Copy(dimensions, 1, newDimensions, 0, dimensions.Length - 1);

            var newIndexPrefix = new int[indexPrefix.Length + 1];
            Array.Copy(indexPrefix, 0, newIndexPrefix, 0, indexPrefix.Length);
            newIndexPrefix[indexPrefix.Length] = i;

            RecursiveCopy(source, destination, newDimensions, mutate, newIndexPrefix);
        }
    }
    else
    {
        var currentIndex = new int[indexPrefix.Length + 1];
        Array.Copy(indexPrefix, 0, currentIndex, 0, indexPrefix.Length);
        for (var i = 0; i < dimensions[0]; i++)
        {
            currentIndex[indexPrefix.Length] = i;
            var value = source.GetValue(currentIndex);
            if (value is TInput)
            {
                var mutated = mutate((TInput)value);
                destination.SetValue(mutated, currentIndex);
            }
            else
            {
                throw new ArgumentException("Different type. Expected " + nameof(TInput));
            }
        }
    }
}

Usage

var transformedArr = Array.CreateInstance(typeof(StatusCode), dimensions);
RecursiveCopy<object, StatusCode>(arr, transformedArr, dimensions, i => i as StatusCode);

You can put real type instead of object

Sign up to request clarification or add additional context in comments.

1 Comment

You saved my day! Thank you very much. Now i have to understand what you have written :D
0

You can do this by using CreateInstance to create your output array (using your dimensions as input), then using GetValue and SetValue to transform your values.

3 Comments

I can't use GetValue and SetValue because i don't know the dimensions of teh Array at compile time. So i don't know if it is a 2x3x5 or a 2x3x7x3, etc. In other words, i can't index the array in my code because i don't know how many dimension i have. I hope i was clear.
Did you look at these functions? They're specifically designed to enable your use case. You can use an array of indexes without compile time knowledge of the rank.
Of course i have looked them. The second parameter is "A one-dimensional array of 32-bit integers that represent the indexes specifying the position of the Array element to get." I can't pass an index because i don't know how indices are composed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.