You can use Enumerable.Range
and Enumerable.ElementAtOrDefault
:
List<List<string>> rotated = Enumerable.Range(0, PersonInfo.Max(list => list.Count))
.Select(i => PersonInfo.Select(list => list.ElementAtOrDefault(i)).ToList())
.ToList();
PersonInfo.Max(list => list.Count)
returns the max-size of the lists. This will be the new size of the main list, in this case 3. Enumerable.Range
is like a for-loop. For every list it will now select all strings at these indexes. If the sizes are different you'll get null
(because of ElementAtOrDefault
).
If the lists had the same size you can apply the same query to get the original list back:
PersonInfo = Enumerable.Range(0, rotated.Max(list => list.Count))
.Select(i => rotated.Select(list => list.ElementAtOrDefault(i)).ToList())
.ToList();
As extension:
public static IEnumerable<IList<T>> Rotate<T>(this IEnumerable<IList<T>> sequences)
{
var list = sequences as IList<IList<T>> ?? sequences.ToList();
int maxCount = list.Max(l => l.Count);
return Enumerable.Range(0, maxCount)
.Select(i => list.Select(l => l.ElementAtOrDefault(i)).ToList());
}
Usage:
IEnumerable<IList<string>> rotated = PersonInfo.Rotate();
IEnumerable<IList<string>> rotatedPersonInfo = rotated.Rotate(); // append ToList to get the original list
List<List<string>>
– Intermingle