If I have a list containing an arbitrary number of lists, like so:
var myList = new List>()
{
new List() { \"a\",
Here's an inefficient variant based on Matrix Transposition:
public static class Ext
{
public static IEnumerable<IEnumerable<T>> Rotate<T>(
this IEnumerable<IEnumerable<T>> src)
{
var matrix = src.Select(subset => subset.ToArray()).ToArray();
var height = matrix.Length;
var width = matrix.Max(arr => arr.Length);
T[][] transpose = Enumerable
.Range(0, width)
.Select(_ => new T[height]).ToArray();
for(int i=0; i<height; i++)
{
for(int j=0; j<width; j++)
{
transpose[j][i] = matrix[i][j];
}
}
return transpose;
}
}
You can do this by using the Select
extension taking a Func<T, int, TOut>
:
var rotatedList = myList.Select(inner => inner.Select((s, i) => new {s, i}))
.SelectMany(a => a)
.GroupBy(a => a.i, a => a.s)
.Select(a => a.ToList()).ToList();
This will give you another List<List<string>>
.
Breakdown
.Select(inner => inner.Select((s, i) => new {s, i}))
For each inner list, we project the list's content to a new anonymous object with two properties: s
, the string value, and i
the index of that value in the original list.
.SelectMany(a => a)
We flatten the result to a single list
.GroupBy(a => a.i, a => a.s)
We group by the i
property of our anonymous object (recall this is the index) and select the s
property as our values (the string only).
.Select(a => a.ToList()).ToList();
For each groups, we changed the enumerable to a list and another list for all the groups.