views:

147

answers:

3

A SDK is returning me an array with multiple dimensions such as:

int[,,] theArray = new int[2,8,12];

I need to visit each element in the array and return the value and the position of the value. I need to do this without knowing the number of dimensions and elements of the array being passed in.

+2  A: 

Use for loops:

for (int i=theArray.GetLowerBound(0);i<=theArray.GetUpperBound(0);++i)
{
    for (int j=theArray.GetLowerBound(1);j<=theArray.GetUpperBound(1);++j)
    {
        for (int k=theArray.GetLowerBound(2);k<=theArray.GetUpperBound(2);++k)
        {
           // do work, using index theArray[i,j,k]
        }
    }
}

If you don't know the number of dimensions in advance, you can use Array.Rank to determine that.

Reed Copsey
Thanks for the answer. My problem is that I do not know the rank or bounds of the array before It is passed to me. Any other suggestions would be really appreciated.
Sci-fi
You can use theArray.Rank to get the rank, and the bounds are automatically determined by my code above.
Reed Copsey
+1  A: 

Would something like this work for you? It recurses the ranks so you can use a foreach() and get an array containing the current item's indices.

class Program
{
 static void Main(string[] args)
 {
  int[, ,] theArray = new int[2, 8, 12];
  theArray[0, 0, 1] = 99;
  theArray[0, 1, 0] = 199;
  theArray[1, 0, 0] = 299;

  Walker w = new Walker(theArray);

  foreach (int i in w)
  {
   Console.WriteLine("Item[{0},{1},{2}] = {3}", w.Pos[0], w.Pos[1], w.Pos[2], i);
  }

  Console.ReadKey();
 }

 public class Walker : IEnumerable<int>
 {
  public Array Data { get; private set; }
  public int[] Pos { get; private set; }

  public Walker(Array array)
  {
   this.Data = array;
   this.Pos = new int[array.Rank];
  }

  public IEnumerator<int> GetEnumerator()
  {
   return this.RecurseRank(0);
  }

  private IEnumerator<int> RecurseRank(int rank)
  {
   for (int i = this.Data.GetLowerBound(rank); i <= this.Data.GetUpperBound(rank); ++i)
   {
    this.Pos.SetValue(i, rank);

    if (rank < this.Pos.Length - 1)
    {
     IEnumerator<int> e = this.RecurseRank(rank + 1);
     while (e.MoveNext())
     {
      yield return e.Current;
     }
    }
    else
    {
     yield return (int)this.Data.GetValue(this.Pos);
    }
   }
  }

  System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  {
   return this.RecurseRank(0);
  }
 }
}
ongle
Excellent example and works very well.
Sci-fi
A: 
Loadmaster