Reputation: 7267
I have a List of list. I want to revert this (rows become columns and columns become rows. I am able to invert it if number of elements are same in inner list. But if number of elements in inner list are different I am not able to do so.
So lets say I have this list
1 2 3 4
5 6 7 8
I get this output
1 5
2 6
3 7
4 8
But if I have input like this, then I receive errors
1
2 3 4
5 6 7
Here is the code,
var invertedRows = matrix.Select(row => row.Count).Concat(new[] {0}).Max();
var result = new Point3D[invertedRows][];
for (var i = 0; i < invertedRows; i++)
{
var invertedColumns = matrix[i].Count;
result[i] = new Point3D[invertedColumns];
for (var j = 0; j < invertedColumns; j++)
result[i][j] = matrix[j][i];
}
matrix.Clear();
matrix.AddRange(result.Select(row => row.ToList()));
Upvotes: 0
Views: 503
Reputation: 460058
Update: (moved first LINQ approach to the bottom since this is much better)
You can use this extension method:
public static List<List<T>> Pivot<T>(this List<List<T>> inputLists, bool removeEmpty, T defaultVal = default(T))
{
if (inputLists == null) throw new ArgumentNullException("inputLists");
if(removeEmpty && !object.Equals(defaultVal, default(T))) throw new ArgumentException("You cannot provide a default value and removeEmpty at the same time!", "removeEmpty");
int maxCount = inputLists.Max(l => l.Count);
List<List<T>> outputLists = new List<List<T>>(maxCount);
for(int i = 0; i < maxCount; i++)
{
List<T> list = new List<T>();
outputLists.Add(list);
for (int index = 0; index < inputLists.Count; index++)
{
List<T> inputList = inputLists[index];
bool listSmaller = inputList.Count <= i;
if (listSmaller)
{
if (!removeEmpty)
list.Add(defaultVal);
}
else
list.Add(inputList[i]);
}
}
return outputLists;
}
Usage:
List<List<int>> lists = new List<List<int>>();
lists.Add(new List<int> { 1 });
lists.Add(new List<int> { 2,3 });
lists.Add(new List<int> { 4,5,6 });
List<List<int>> result = lists.Pivot(true);
foreach(List<int> list in result)
Console.WriteLine(string.Join(",", list));
Output:
1,2,4
3,5
6
Old, accepted version that is less efficient and does not support different default values and removal of empty elements following:
public static List<List<T>> Pivot<T>(this List<List<T>> inputLists)
{
int maxCount = inputLists.Max(l => l.Count);
var result = Enumerable.Range(0, maxCount)
.Select(index => inputLists.Select(list => list.ElementAtOrDefault(index))
.ToList())
.ToList();
return result;
}
Note that it replaces all non existent indices with the default value of that type.
Test:
List<List<int>> lists = new List<List<int>>();
lists.Add(new List<int> { 1 });
lists.Add(new List<int> { 2,3 });
lists.Add(new List<int> { 4,5,6 });
List<List<int>> result = lists.Pivot();
foreach(List<int> list in result)
Console.WriteLine(string.Join(",", list));
Output:
1,2,4
0,3,5
0,0,6
Upvotes: 3
Reputation: 1934
code should look something like this
List<List<int>> cols = new List<List<int>>();
cols.Add(new List<int>() { 1 });
cols.Add(new List<int>() { 2,3,4 });
cols.Add(new List<int>() { 5,6,7 });
int[][] result = new int[100][];
for (int i = 0; i < cols.Count; i++)
{
for (int j = 0; j < cols[i].Count; j++)
{
if (result[j] == null)
{
result[j] = new int[100];
}
if (cols[i].Count < j)
{
result[j][i] = 0;
} else
{
result[j][i] = cols[i][j];
}
}
}
If you debug your code you should find out easily where exactly is the problem. Probably something like calling 4th column from a 3 column array/list.
Upvotes: 1
Reputation: 4836
well your input is not of the same length.
what do you expect to see in the first column of the output? How does your code allow for this?
Upvotes: 1