LINQ swap columns into rows

前端 未结 5 1951
死守一世寂寞
死守一世寂寞 2020-12-06 10:44

Is there a fancy LINQ expression that could allow me to do the following in a much more simpler fashion. I have a List>, assuming the L

5条回答
  •  难免孤独
    2020-12-06 11:20

    Here's one that works for rectangular (non-ragged) matrices. The C# code here works cut-and-paste into LinqPad, a free, interactive C# programming tool.

    I define a postfix operator (that is, an extension method) "Transpose." Use the operator as follows:

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

    resulting in something like this:

    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
    

    The gist of the implementation of this operator is the following

        public static IEnumerable> Transpose(this IEnumerable> xss)
        {
            var heads = xss.Heads();
            var tails = xss.Tails();
    
            var empt = new List>();
            if (heads.IsEmpty())
                return empt;
            empt.Add(heads);
            return empt.Concat(tails.Transpose());
        }
    

    Here is the full implementation, with some lines commented out that you can uncomment to monitor how the function works.

    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 Heads(this IEnumerable> xss)
        {
            Debug.Assert(xss != null);
            if (xss.Any(xs => xs.IsEmpty()))
                return new List();
            return xss.Select(xs => xs.First());
        }
    
        public static bool IsEmpty(this IEnumerable xs)
        {
            return xs.Count() == 0;
        }
    
        public static IEnumerable> Tails(this IEnumerable> xss)
        {
            return xss.Select(xs => xs.Skip(1));
        }
    
        public static IEnumerable> Transpose(this IEnumerable> 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>();
            if (heads.IsEmpty())
                return empt;
            empt.Add(heads);
            return empt.Concat(tails.Transpose())
    //          .Dump("empt")
                ;
        }
    }
    

提交回复
热议问题