fhnaseer
fhnaseer

Reputation: 7267

Invert/Rotate List of list (List<List<int >) having different items in innerlist

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

Answers (3)

Tim Schmelter
Tim Schmelter

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

Milan Halada
Milan Halada

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

John Nicholas
John Nicholas

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

Related Questions