2016-10-21 12 views
0

我正面臨以下問題:有一個網格,每個網格單元都有一個位置。這種網格的一個例子可能是下列之一:如何按網格的部分按平方數量進行分組?

_________________________________________ 
|  |  |  |  |  | 
| (0,0) | (1,0) | (2,0) | (3,0) | (4,0) | 
|_______|_______|_______|_______|_______| 
|  |  |  |  |  | 
| (0,1) | (1,1) | (2,1) | (3,1) | (4,1) | 
|_______|_______|_______|_______|_______| 
|  |  |  |  |  | 
| (0,2) | (1,2) | (2,2) | (3,2) | (4,2) | 
|_______|_______|_______|_______|_______| 
|  |  |  |  |  | 
| (0,3) | (1,3) | (2,3) | (3,3) | (4,3) | 
|_______|_______|_______|_______|_______| 
|  |  |  |  |  | 
| (0,4) | (1,4) | (2,4) | (3,4) | (4,4) | 
|_______|_______|_______|_______|_______| 

我需要創建,賦予了許多ň功能,最多產生的二次N×N個金額,數量組。例如,對於N = 2,每個組將包含至多2×2個單元,組1將包含[(0,0)(1,0)(0,1)(1,1)],組2 [(2 ,0)(3,0)(2,1)(3,1)],組3將只包含[(4,0)(4,1)],依此類推。我決定使用LINQ Group By函數,但是它需要一個lambda表達式,它必須計算一個必須與每個組相同的數字。因此,我正在看一個表達式,對於我的n = 2的問題,必須返回[(0,0)(1,0)(0,1)(1,1)]的相同數字,另一個數字爲[(2,0)(3,0)(2,1)(3,1)],對於[(4,0)(4,1)]而言是不同的一個,等等...

哪種的表達可以實現該屬性?

謝謝

回答

1

爲了使用「羣組By'操作,你需要定義一鍵組。 在這種情況下,如果是關於網格,我唯一可能想到的關鍵是基於網格中行/列索引的計算結果。 我覺得有點難以解釋我選擇的純文本計算,所以我希望下面的例子能夠爲我說話。

請問這個答案或幫助你的問題?

測試數據/設置

var grid = new List<List<string>>(); 

grid.Add(new List<string>(new[] { "0,0", "1,0", "2,0", "3,0", "4,0" })); 
grid.Add(new List<string>(new[] { "0,1", "1,1", "2,1", "3,1", "4,1" })); 

grid.Add(new List<string>(new[] { "0,2", "1,2", "2,2", "3,2", "4,2" })); 
grid.Add(new List<string>(new[] { "0,3", "1,3", "2,3", "3,3", "4,3" })); 

grid.Add(new List<string>(new[] { "0,4", "1,4", "2,4", "3,4", "4,4" })); 

// Quadratic group factor. 
int n = 2; 

解決方案1 ​​ - Lambda表達式

var result_1 = grid 

    // Create quadratic groups by calculating the combined index of the row+column with the quadratic group factor. 
    .SelectMany(r => 
     r.GroupBy(c => 
      (int)Math.Floor((double)grid.IndexOf(r)/(double)n) 
       + "_" + 
      (int)Math.Floor((double)r.IndexOf(c)/(double)n) 
     ) 
    ) 

    // Combine all same keys together in one group. 
    .GroupBy(g => g.Key) 

    // Get all results per group. 
    .Select(gg => gg.SelectMany(g => g).ToList()) 

    // ToList() because it's easier to inspect the value of the result while debugging. 
    .ToList(); 

// Short version: 
var result_2 = grid 
    .SelectMany(r => 
     r.GroupBy(c => 
      (int)Math.Floor((double)grid.IndexOf(r)/(double)n) + "_" + (int)Math.Floor((double)r.IndexOf(c)/(double)n) 
     ) 
    ) 
    .GroupBy(g => g.Key) 
    .Select(gg => gg.SelectMany(g => g).ToList()) 
    .ToList(); 

解決方案2 - 舊校園循環,可能更容易/更好地理解。

var result_3 = new List<List<string>>(); 

// Range (amount of both 'rows' and 'columns' since it's a grid). 
int range = (int)Math.Ceiling((double)grid.Count/(double)n); 

// Loop through 'rows'. 
for(var y = 0; y < range; y++) 
{ 
    int skipRowsAmount = (y * n); 
    int takeRowsAmount = n; 

    // Get all 'rows' to split in groups. 
    var rows = grid.Skip(skipRowsAmount).Take(takeRowsAmount).ToList(); 

    // Loop through 'columns'. 
    for (var x = 0; x < range; x++) 
    { 
     int skipColumnsAmount = (x * n); 
     int takeColumnsAmount = n; 

     // Get all 'columns' from all 'rows' to split in groups. 
     var quadraticColumns = rows.SelectMany(l => l.Skip(skipColumnsAmount).Take(takeColumnsAmount)).ToList(); 

     // Add the quadratic columns group to the result. 
     result_3.Add(quadraticColumns); 
    } 
} 

編輯 - 代碼從字符串更改組關鍵整數

.SelectMany(r => 
    r.GroupBy(c => 
     (((int)Math.Floor((double)grid.IndexOf(r)/(double)n)) * ((int)Math.Ceiling((double)grid.Count/(double)n))) 
      + 
     (int)Math.Floor((double)r.IndexOf(c)/(double)n) 
    ) 
) 
+0

爲了什麼,我想實現的,你的第一個解決方案工作得非常好,謝謝你!儘管如此,你使用了一個字符串作爲關鍵字。有什麼辦法可以把它變成一個整數並以同樣的方式工作?提前致謝。 –

+1

是的。您可以通過數學計算將組鍵例如從「0_0」更改爲0(int)。我在上面的主文章中附加了一個例子。它所做的是直接計算網格中每個列的組編號,然後將其分組。 – Richard