我遇到以下问题:有一个网格,每个网格单元都有一个位置。这种网格的一个例子可以是以下一个:
_________________________________________
| | | | | |
| (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 ,最多创建该数字的二次 NxN 数量的组。例如,对于N = 2,每组最多包含2x2个单元,第1组将包含[(0,0)(1,0)(0,1)(1,1)],第2组[(2 ,0)(3,0)(2,1)(3,1)],第3组只包含[(4,0)(4,1)]等等。
我使用C#,所以这在概念上是按操作分组,我决定使用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)]等的不同...
哪种表达可以实现该属性?
谢谢
答案 0 :(得分:1)
要使用' Group By' -operation,您需要定义要分组的键。 在这种情况下,如果它是关于网格的,我能想到的唯一可能的关键是基于网格中行/列索引的计算结果。 我觉得解释我在纯文本中选择的计算有点困难,所以我希望下面的例子可以帮我说话。
这回答或帮助解决您的问题吗?
测试数据/设置
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 - Oldschool循环,可能更容易/更好理解。
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)
)
)