NMJGD
NMJGD

Reputation: 11

How To create unknown-multidimensional parameter?

I would Like to know if it is possible to create a generic multidimensional parameter. I am making a generic list/array shuffle class which would have a static method which gets an IEnumerable parameter and returns the same but already shuffled. The Problem is I don't know how to make the parameter so generic that it would get any number of dimensions array/list.

Thank you in advance.

Here is the Code I Wrote For Now:

 public static IEnumerable<T> OneDimensionalShuffle<T>(IEnumerable<T> array)
    {
        var originalList = array.ToList();
        var shuffledList = new List<T>();

        var rand = new Random();

        for (var i = originalList.Count - 1; i >= 0; i--)
        {
            var randomArrayPosition = rand.Next(i + 1); //i+1 because maxValue is exclusive
            shuffledList.Add(originalList[randomArrayPosition]); //Add random point to the shuffledList
            originalList.RemoveAt(randomArrayPosition); //Remove element which was already added to shuffledList
        }

        array = shuffledList;
        return array;
    }

Upvotes: 0

Views: 107

Answers (1)

JonasH
JonasH

Reputation: 36649

As far as I know there is no way to access a generic typed multi-dimensional array of arbitrary rank.

Alternative 1: Use a untyped array

Array arr = new int[1,1];
var rank = arr.Rank;
var value = arr.GetValue(0,0);

Downside with this is that it is rather slow, and will cause a bunch of boxing.

Alternative 2: Use a custom multidimensional type

 public class MyMultiDimensionalArray<T>{
      public T[] backingDataStorage {get;}
      public int Rank {get;}
      public int[] Length {get;}
      public T GetValue(params int[] indices){
           // Math to convert the indices to a one dimensional value
      }
 }

An advantage of this is that you can use generic types, and allow direct access to the underlying array. The downside is that you need to write a bunch of math to convert a index of arbitrary rank to a 1d index. A variant of this is to have different types, My2DArray, My3DArray etc, and a common interface.

Alternative 3: Define as many methods as you need dimensions

 public static void MyMethod<T>(T[]) { /*...*/}
 public static void MyMethod<T>(T[,]) { /*...*/}
 public static void MyMethod<T>(T[,,]) { /*...*/}
 public static void MyMethod<T>(T[,,,]) { /*...*/}

this is fairly easy to do and allow generic typing, but will require a bunch of code-duplication.

In my experience 1d, 2d and 3d arrays are most common. I have never seen a 4d array used in the wild. And even 3d arrays can often become so large that it can be better to store one dimension as a jagged array, i.e. int[][,], since it avoids the need for a huge continuous memory block, allow locking individual slices etc. I prefer to use custom multidimensional array types, since I find it quite common to want linear access to the data, for things like serialization, or shuffling.

Upvotes: 1

Related Questions