2016-10-21 11 views
0

私は次の問題に直面しています:1つのグリッドと各グリッドセルに位置があります。そのようなグリッドの一例は、以下のいずれかになります。私はN数を与え、関数を作成する必要がグリッドの一部分を二次的な量でグループ化するにはどうすればいいですか?

_________________________________________ 
|  |  |  |  |  | 
| (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の場合、各グループは最大で2x2のセルを含み、グループ1は[(0,0)(1,0)(1,1)]、グループ2 [(2 、0)(3,0)(2,1)(3,1)]の場合、グループ3は[(4,0)(4,1)]というようになります。

私はC#を使用していますが、これは概念的には操作単位であり、LINQ グループ化関数を使用することに決めましたが、各グループに対して同じ数でなければならないラムダ式が必要です。したがって、私は、n = 2の私の問題では、[(0、0)(1,0)(0,1)(1,1)]と同じ番号を返さなければならないという表現を見ています。 [(4,0)(4,1)]などのための異なるもの...

どのような種類の[(2,0)(3,0)(2,1)(3,1)]表現の自由はその財産を満たすことができますか?

は、「グループBy'操作を使用するためには、あなたは上のグループにキーを定義する必要があなたに

答えて

1

ありがとうございます。 この場合、グリッドの場合、考えられる唯一のキーは、グリッドの行/列のインデックスに基づく計算の結果です。 私がプレーンテキストで選んだ計算を説明するのはちょっと難しいので、以下の例が私の話をすることを願っています。

これはあなたの質問にお答えしますか?

テストデータ/設定

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 - ラムダ式

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

関連する問題