反转/旋转列表(List <list <int>)列表,其中包含innerlist </list <int>中的不同项

时间:2014-04-29 12:18:00

标签: c# list

我有一份清单。我想恢复这个(行变成列,列成为行。如果内部列表中的元素数量相同,我可以反转它。但是如果内部列表中的元素数量不同,我无法这样做。

让我说我有这个清单

1 2 3 4
5 6 7 8

我得到了这个输出

1 5
2 6
3 7
4 8

但如果我有这样的输入,那么我会收到错误

1 
2 3 4
5 6 7

这是代码,

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

3 个答案:

答案 0 :(得分:2)

更新 :(将第一个LINQ方法移到底部,因为这样做要好得多)

您可以使用此扩展方法:

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

用法:

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

输出:

1,2,4
3,5
6

,接受的效率较低且不支持不同默认值并删除以下空元素的版本:

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

请注意,它会将所有不存在的索引替换为该类型的默认值。

测试:

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

输出:

1,2,4
0,3,5
0,0,6

答案 1 :(得分:1)

你输入的长度不一样。

您希望在输出的第一列中看到什么? 你的代码如何允许这个?

答案 2 :(得分:1)

代码看起来应该是这样的

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];
        }
    }
}

如果您调试代码,您应该很容易找到问题的确切位置。可能类似于从3列数组/列表中调用第4列。