Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ将列交换为行_C#_Linq - Fatal编程技术网

C# LINQ将列交换为行

C# LINQ将列交换为行,c#,linq,C#,Linq,有没有一个别致的LINQ表达式可以让我用一种更简单的方式来做下面的事情。我有一个列表,假设列表是二维矩阵中的列,我想将列列表交换为行列表。我有以下显而易见的解决方案: int columns = 5; var values; // assume initialised as List<List<double>>() var listOfRows = new List<List<double>>(); for (int i = 0; i <

有没有一个别致的LINQ表达式可以让我用一种更简单的方式来做下面的事情。我有一个列表,假设列表是二维矩阵中的列,我想将列列表交换为行列表。我有以下显而易见的解决方案:

int columns = 5;
var values; // assume initialised as List<List<double>>()

var listOfRows = new List<List<double>>();
for (int i = 0; i < columns ; i++)
{
    List<double> newRow = new List<double>();
    foreach (List<double> value in values)
    {
        newRow.Add(value[i]);
    }
    listOfRows.Add(newRow);
}

下面是一个Linq表达式,它可以实现您想要的功能—看它,我个人还是坚持使用嵌套的foreach循环—更易于阅读:

var columnList= new  List<List<double>>();
columnList.Add(new List<double>() { 1, 2, 3 });
columnList.Add(new List<double>() { 4, 5, 6 });
columnList.Add(new List<double>() { 7, 8, 9 });
columnList.Add(new List<double>() { 10, 11, 12 });

int columnCount = columnList[0].Count;
var rowList = columnList.SelectMany(x => x)
                        .Select((x, i) => new { V = x, Index = i })
                        .GroupBy(x => (x.Index + 1) % columnCount)
                        .Select(g => g.Select( x=> x.V).ToList())
                        .ToList();

您可以非常轻松地LINQify内部循环:

vector.AddRangevalues.Selectvalue=>value[i]

这是否会提高可读性完全取决于您

var inverted = Enumerable.Range(0, columnCount)
               .Select(index => columnList.Select(list => list[index]));
简而言之,我们从一个范围枚举列索引,并使用它收集每个列表的第n个元素


请注意,您需要检查每个列表的列数是否相同。

这里有一个适用于矩形非参差不齐矩阵的列表。这里的C代码可以剪切粘贴到一个免费的交互式C编程工具中

我定义了一个后缀运算符,即扩展方法转置。按如下方式使用运算符:

    var rand = new Random();

    var xss = new [] {
        new [] {rand.NextDouble(), rand.NextDouble()},
        new [] {rand.NextDouble(), rand.NextDouble()},
        new [] {rand.NextDouble(), rand.NextDouble()},
    };

    xss.Dump("Original");
    xss.Transpose().Dump("Transpose");
结果是这样的:

Original
0.843094345109116
0.981432441613373

0.649207864724662
0.00594645645746331

0.378864820291691
0.336915332515219


Transpose
0.843094345109116
0.649207864724662
0.378864820291691

0.981432441613373
0.00594645645746331
0.336915332515219
该操作符的实现要点如下

    public static IEnumerable<IEnumerable<T>> Transpose<T>(this IEnumerable<IEnumerable<T>> xss)
    {
        var heads = xss.Heads();
        var tails = xss.Tails();

        var empt = new List<IEnumerable<T>>();
        if (heads.IsEmpty())
            return empt;
        empt.Add(heads);
        return empt.Concat(tails.Transpose());
    }
下面是完整的实现,注释掉了一些行,您可以取消注释以监视函数的工作方式

void Main()
{
    var rand = new Random();

    var xss = new [] {
        new [] {rand.NextDouble(), rand.NextDouble()},
        new [] {rand.NextDouble(), rand.NextDouble()},
        new [] {rand.NextDouble(), rand.NextDouble()},
    };
    xss.Dump("Original");
    xss.Transpose().Dump("Transpose");
}

public static class Extensions
{
    public static IEnumerable<T> Heads<T>(this IEnumerable<IEnumerable<T>> xss)
    {
        Debug.Assert(xss != null);
        if (xss.Any(xs => xs.IsEmpty()))
            return new List<T>();
        return xss.Select(xs => xs.First());
    }

    public static bool IsEmpty<T>(this IEnumerable<T> xs)
    {
        return xs.Count() == 0;
    }

    public static IEnumerable<IEnumerable<T>> Tails<T>(this IEnumerable<IEnumerable<T>> xss)
    {
        return xss.Select(xs => xs.Skip(1));
    }

    public static IEnumerable<IEnumerable<T>> Transpose<T>(this IEnumerable<IEnumerable<T>> xss)
    {
//      xss.Dump("xss in Transpose");
        var heads = xss.Heads()
//          .Dump("heads in Transpose")
            ;
        var tails = xss.Tails()
//          .Dump("tails in Transpose")
            ;

        var empt = new List<IEnumerable<T>>();
        if (heads.IsEmpty())
            return empt;
        empt.Add(heads);
        return empt.Concat(tails.Transpose())
//          .Dump("empt")
            ;
    }
}

我将上面的一些答案结合起来,有时列和行与原始答案或我习惯的惯例相反:行指第一个索引,列指内部第二个索引。e、 g.值[行][列]

    public static List<List<T>> Transpose<T>(this List<List<T>> values)
    {
        if (values.Count == 0 || values[0].Count == 0)
        {
            return new List<List<T>>();
        }

        int ColumnCount = values[0].Count;

        var listByColumns = new List<List<T>>();
        foreach (int columnIndex in Enumerable.Range(0, ColumnCount))
        {
            List<T> valuesByColumn = values.Select(value => value[columnIndex]).ToList();
            listByColumns.Add(valuesByColumn);
        }
        return listByColumns;
    }            
事实上,“行”和“列”这个词只是我们对行和列中的数据进行思考的惯例,有时比解决它们更容易混淆

实际上,我们只是将内部索引替换为外部索引。或者翻转索引。因此,我们也可以定义以下扩展方法。我再次借用了上面的解决方案,只是把它放进我觉得可读且相当紧凑的东西中

需要检查内部列表的大小是否相同

    public static List<List<T>> InsideOutFlip<T>(this List<List<T>> values)
    {
        if (values.Count == 0 || values[0].Count == 0)
        {
            return new List<List<T>>();
        }

        int innerCount = values[0].Count;

        var flippedList = new List<List<T>>();
        foreach (int innerIndex in Enumerable.Range(0, innerCount))
        {
            List<T> valuesByOneInner = values.Select(value => value[innerIndex]).ToList();
            flippedList.Add(valuesByOneInner);
        }
        return flippedList;
    }            

Hmm的可读性可能不那么友好。我的版本和Linq表达式之间的性能会一样吗?@Seth:我假设它的性能比你的版本差,因为它必须展平然后重新分组,而for循环直接使用列表项的索引来创建行lists@DBM:AddRange的定义是什么?
    public static List<List<T>> InsideOutFlip<T>(this List<List<T>> values)
    {
        if (values.Count == 0 || values[0].Count == 0)
        {
            return new List<List<T>>();
        }

        int innerCount = values[0].Count;

        var flippedList = new List<List<T>>();
        foreach (int innerIndex in Enumerable.Range(0, innerCount))
        {
            List<T> valuesByOneInner = values.Select(value => value[innerIndex]).ToList();
            flippedList.Add(valuesByOneInner);
        }
        return flippedList;
    }