David Jiménez Martínez - 1 year ago 51

C# Question

I'm facing the following problem: The have one grid and each grid cell has a position. One example of such grid could be the following one:

`_________________________________________`

| | | | | |

| (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) |

|_______|_______|_______|_______|_______|

I need to create a function that, given a number

I'm using C#, so this is conceptually a Group by operation, I decided to use LINQ

Which kind of expression could fulfil that property?

Thank you

Answer Source

In order to use a 'Group By'-operation, you need to define a key to group on. In this case, if it's about a grid, the only possible key I could think of is the result of a calculation based on the index of the row/column in the grid. I find it a bit difficult to explain the calculation I chose in plain text so I hope the example below does the talk for me.

Does this answer or help with your question?

**Test data / settings**

```
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;
```

**Solution 1 - Lambda expression**

```
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();
```

**Solution 2 - Oldschool loop, probably easier/better to understand.**

```
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);
}
}
```