2013-06-23 60 views
1

我的任務是生成一個數組的所有可能的索引組合,其中該數組可能是一個具有不同數量元素的單個,2D,3D,4D ... nD數組。目前,我只能使用嵌套for循環支持單個,二維和三維數組。動態生成數組索引的所有可能組合

例子:

byte[,,] sampleArray = new byte[5,4,3]; 

Generated Index Combinations: 
sampleArray[0,0,0] 
sampleArray[0,0,1] 
sampleArray[0,0,2] 
sampleArray[0,1,0] 
sampleArray[0,1,1] 
sampleArray[0,1,2] 
sampleArray[0,2,0] 
sampleArray[0,2,1] 
sampleArray[0,2,2] 
sampleArray[0,3,0] 
sampleArray[0,3,1] 
sampleArray[0,3,2] 
sampleArray[1,0,0] 
sampleArray[1,0,1] 
sampleArray[1,0,2] 
sampleArray[1,1,0] 
sampleArray[1,1,1] 
sampleArray[1,1,2] 
sampleArray[1,2,0] 
sampleArray[1,2,1] 
sampleArray[1,2,2] 
sampleArray[1,3,0] 
sampleArray[1,3,1] 
sampleArray[1,3,2] 
sampleArray[2,0,0] 
sampleArray[2,0,1] 
sampleArray[2,0,2] 
sampleArray[2,1,0] 
sampleArray[2,1,1] 
sampleArray[2,1,2] 
sampleArray[2,2,0] 
sampleArray[2,2,1] 
sampleArray[2,2,2] 
sampleArray[2,3,0] 
sampleArray[2,3,1] 
sampleArray[2,3,2] 
sampleArray[3,0,0] 
sampleArray[3,0,1] 
sampleArray[3,0,2] 
sampleArray[3,1,0] 
sampleArray[3,1,1] 
sampleArray[3,1,2] 
sampleArray[3,2,0] 
sampleArray[3,2,1] 
sampleArray[3,2,2] 
sampleArray[3,3,0] 
sampleArray[3,3,1] 
sampleArray[3,3,2] 
sampleArray[4,0,0] 
sampleArray[4,0,1] 
sampleArray[4,0,2] 
sampleArray[4,1,0] 
sampleArray[4,1,1] 
sampleArray[4,1,2] 
sampleArray[4,2,0] 
sampleArray[4,2,1] 
sampleArray[4,2,2] 
sampleArray[4,3,0] 
sampleArray[4,3,1] 
sampleArray[4,3,2] 

我的代碼:

 protected void GenerateIndexCombinations(int indexCounter, 
    ref List<List<int>> indexList, Array arr, ref List<int> index) 
     { 
      int dimSize1 = arr.GetLength(0); 
      int dimSize2 = 0; 
      int dimSize3 = 0; 
      if (indexCounter > 1) 
      { 
       dimSize2 = arr.GetLength(1); 
       if (indexCounter > 2) 
       { 
        dimSize3 = arr.GetLength(2); 
       } 
      } 

      for (int a = 0; a < dimSize1; a++) 
      { 
       if (dimSize2 > 0) 
       { 
        for (int b = 0; b < dimSize2; b++) 
        { 
         if (dimSize3 > 0) 
         { 
          for (int c = 0; c < dimSize3; c++) 
          { 
           index = new List<int>(); 
           index.Add(a); 
           index.Add(b); 
           index.Add(c); 
           indexList.Add(index); 
          } 
         } 
         else 
         { 
          index = new List<int>(); 
          index.Add(a); 
          index.Add(b); 
          indexList.Add(index); 
         } 
        } 
       } 
       else 
       { 
        index = new List<int>(); 
        index.Add(a); 
        indexList.Add(index); 
       } 
      } 
     } 

其中:
INT indexCounter是維數。
陣列ARR是通過使用反射訪問的數組:

Array arr = fieldInfoArray[j].GetValue(_classInstance) as Array; 


ref List<List<int>> indexList將是組合的容器。
ref List<int> index是添加到indexList的個人編號。

由於尺寸大小不固定,以及每個維度的元素數量,我想要動態生成組合來代替我的嵌套for循環,有沒有辦法做到這一點?

感謝您的回答。

回答

3

Eric Lippert有blogged關於這個問題。在您的具體情況下,您正在尋找Enumerable.Range(0, 5)Enumerable.Range(0, 4)Enumerable.Range(0, 3)的笛卡爾乘積。在一般情況下,你想是這樣的:

var dimensions = 
    Enumerable.Range(0, array.Rank) 
       .Select(r => Enumerable.Range(0, array.GetLength(r))); 

,然後調用Eric的方法上dimensions。在這裏,我使用Array.Rank來獲得矩陣的維數,然後使用Array.GetLength來獲得每個維度的長度,然後動態生成我們需要計算笛卡爾乘積的序列。因此,對於每個維度,我們將該維度投影到array沿該維度的有效索引序列。因此,對於

T[,,...,] array = new T[a_1, a_2, ..., a_n]; 

我們最終dimensions等於序列

(Enumerable.Range(0, a_1), 
Enumerable.Range(0, a_2), 
. 
. 
., 
Enumerable.Range(0, a_n) 
) 

using System.Linq; 
using System.Collections.Generic; 
using System; 

static class EnumerableExtensions { 
    // credit: Eric Lippert 
    public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
     this IEnumerable<IEnumerable<T>> sequences 
    ) { 
     IEnumerable<IEnumerable<T>> emptyProduct = 
      new[] { Enumerable.Empty<T>() }; 
     return sequences.Aggregate(
      emptyProduct, 
      (accumulator, sequence) => 
       from accseq in accumulator 
       from item in sequence 
       select accseq.Concat(new[] { item }) 
     ); 
    } 
} 

class Program { 
    public static void Main(string[] args) { 
     int[,,] array = new int[5, 4, 3]; 
     var dimensions = 
      Enumerable.Range(0, array.Rank) 
         .Select(r => Enumerable.Range(0, array.GetLength(r))); 
     var indexes = dimensions.CartesianProduct(); 
     foreach(var index in indexes) { 
      Console.WriteLine(String.Join(",", index)); 
     } 
    } 
} 
+0

傑森您好,我試圖在博客使用的代碼,但我仍然不能得到的組合。對不起,因爲我是C#編碼新手。 :( – ron

+0

@Ron Reyes:很抱歉聽到這個消息,我的代碼和Eric的代碼一起工作,但我已經給你提供了一個完整的示例。 – jason

+0

好吧,我會再試一次,我只是不知道如何使用Console.WriteLine查看結果 – ron

相關問題