2013-05-08 72 views
0

這個很難解釋!對不起,但這裏有... 我有一些數據[X] [Y] [Z]的3D數組,我喜歡檢查大約10種不同的組合條件,並且只在匹配時才保留數據。例:算法:檢查3D陣列中的條件

   X   Y  Z 
//myData[1..1000000][1..10][1..10].foo // foo is an int 

X[i].Y[ii].Z[iii].foo; // X is a container, Y= 1 to 10 levels. And Z= objects 

//I want to apply a "filter" to the Z objects... 

可以說,我想找到所有這些組合中的「富」之小,比兩個數字大,只保留那些ž對象

對於下一個迭代我想找到可以說只有在「foo」是素數的情況下,仍然只保留Z個對象

等等對於更多條件,導致列表越來越小。 它們的執行順序無關緊要。 我有點知道如何去做,但我最終在一些非常討厭的循環... 任何想法?也許添加到另一個列表比從原始列表中刪除更快? 在此先感謝!

+0

是真實的,我想它。併爲新條件傳遞新陣列,構建新陣列,檢查新條件,等等...... – 2013-05-08 15:44:31

+0

爲什麼不一次檢查所有條件?它會讓你下降到一個3層for循環。 – XGundam05 2013-05-08 15:45:33

+0

嗯,我認爲代碼將很難維護/添加/更改條件..但我可以試一試 – 2013-05-08 15:53:50

回答

2

當你想鏈接這樣的邏輯,我想你真的想使用Linq。不幸的是,在多維數組上使用Linq會很麻煩。但是,有了一些輔助方法,我們可以將數據數組轉換爲更有用的方法。首先,讓我們構建的包裝類爲具有與之相關聯的3個維度的任何物體:

public class ThreeDimensionalArrayExtension<T> { 
    public int X { get; set; } 
    public int Y { get; set; } 
    public int Z { get; set; } 
    public T Value { get; set; } 
} 

接下來,讓我們寫出3- dimsensional陣列轉換爲新的類型的IEnumerables一個輔助方法:

public static class ThreeDimensionalArrayExtensionMethods { 
    public static IEnumerable<ThreeDimensionalArrayExtension<T>> ConvertArray<T>(this T[,,] foos) { 
     for(var x = 0; x < foos.GetLength(0); x++) { 
      for (var y = 0; y < foos.GetLength(1); y++) { 
       for (var z = 0; z < foos.GetLength(2); z++) { 
        yield return new ThreeDimensionalArrayExtension<T> { X = x, Y = y , Z = z, Value = foos[x, y, z] }; 
       } 
      } 
     } 
    } 
} 

請注意,由於我們正在使用迭代器塊(yield-return模式),所以調用此方法實際上並不執行任何計算。

現在我們可以在您的三維陣列上使用Linq的強大功能來過濾它,但是我們想要!

myData.ConvertArray().Where(d => d.Value.Foo > 5) 
        .Where(d => IsPrime(d.Value.Foo)) 
        .Where(...); 

編輯: 我看到你正在使用3嵌套類,而不是一個多維數組,我以爲你是使用。目標仍然應該是將該對象轉換爲IEnumerable,您可以非常輕鬆地鏈接Linq查詢來過濾或投影數據。在你的情況下,你可以這樣做:

public static class ThreeDimensionalArrayExtensionMethods { 
    public static IEnumerable<ThreeDimensionalArrayExtension<X>> ConvertArray(this X[] foos) { 
     for(var x = 0; x < foos.Count(); x++) { 
      for (var y = 0; y < foos[x].Count(); y++) { 
       for (var z = 0; z < foos[x][y].Count(); z++) { 
        yield return new ThreeDimensionalArrayExtension<T> { X = x, Y = y , Z = z, Value = foos[x][y][z] }; 
       } 
      } 
     } 
    } 
} 

然後使用相同的調用ConvertArray,然後使用上面所述的過濾Where子句。

如果你不關心X/Y/Z指數,也可以只使用SelectMany項目多維列表到一個單一的維列表:

X.SelectMany(y => y.SelectMany(z => z)).Where(z => z.Foo > 5); 
+0

這是假設你正在使用一個多維數組,而不是一個鋸齒狀的數組。 – 2013-05-08 16:34:47

+0

哇!感謝您花時間寫下所有這些!令人印象深刻!我需要學習並嘗試linq。 – 2013-05-08 16:35:21

+0

實際上使用3個類,與列表鏈接在一起,所以它實際上是X [0] .Y [0] .Z [0] .foo;但我猜想同樣的事情.... – 2013-05-08 16:36:12