转换一个实体对象-列到行并重新组合-C#Linq

本文关键字:新组合 组合 -C#Linq -列 一个 实体 转换 对象 | 更新日期: 2023-09-27 18:27:13

我得到一个实体对象,如下所示:

{qid=1110, cid=94, gid=3, sid=10, cs=6}
{qid=1110, cid=95, gid=3, sid=10, cs=4}
{qid=1110, cid=96, gid=3, sid=10, cs=6}
{qid=1110, cid=97, gid=3, sid=10, cs=0}
{qid=1111, cid=94, gid=3, sid=10, cs=5}
{qid=1111, cid=95, gid=3, sid=10, cs=5}
{qid=1111, cid=96, gid=3, sid=10, cs=5}
{qid=1111, cid=97, gid=3, sid=10, cs=5}
{qid=1110, cid=94, gid=4, sid=10, cs=6}
{qid=1110, cid=95, gid=4, sid=10, cs=4}
{qid=1110, cid=96, gid=4, sid=10, cs=6}
{qid=1110, cid=97, gid=4, sid=10, cs=4}

但我需要显示或转换如下:

qid || cid1cs || cid2cs || cid3cs || cid4cs || avg_cs || gid || sid
----------------------------------------------------------------------
1110||    6   ||    4   ||    6   ||     0  ||   4    || 3   || 10
----------------------------------------------------------------------
1110||    6   ||    4   ||    6   ||     4  ||   5    || 4   || 10
----------------------------------------------------------------------
1111||    5   ||    5   ||    5   ||     5  ||   5    || 3   || 10
----------------------------------------------------------------------

其中cid1cs是cid=94的cs,cid2cs=95的cs,依此类推。。avg_cs是所有4个cs(cid1cs、cid2cs..)的平均值,需要对gid、sid和qid执行分组和排序。

在LINQ中可以做到这一点吗?我正在使用C#

有人能帮忙吗?

提前感谢

转换一个实体对象-列到行并重新组合-C#Linq

我给你举了一个例子,但请记住,这非常容易出错!但它是有效的。当行数少于4行时,它将失败。

我认为GetHashCode()有一个更好的实现,但这会起作用。

    public class Triplet : IEquatable<Triplet>
    {
        public int Value1 { get; set; }
        public int Value2 { get; set; }
        public int Value3 { get; set; }
        public override int GetHashCode()
        {
            return Value1.GetHashCode() + Value2.GetHashCode() + Value3.GetHashCode();
        }
        public bool Equals(Triplet other)
        {
            int d1 = this.Value1.CompareTo(other.Value1);
            if (d1 != 0)
                return false;
            int d2 = this.Value2.CompareTo(other.Value2);
            if (d2 != 0)
                return false;
            int d3 = this.Value3.CompareTo(other.Value3);
            if (d3 != 0)
                return false;
            return true;
        }
    }

这个linq代码:

        var data = new[] 
        {
            new {qid=1110, cid=94, gid=3, sid=10, cs=6},
            new {qid=1110, cid=95, gid=3, sid=10, cs=4},
            new {qid=1110, cid=96, gid=3, sid=10, cs=6},
            new {qid=1110, cid=97, gid=3, sid=10, cs=0},
            new {qid=1111, cid=94, gid=3, sid=10, cs=5},
            new {qid=1111, cid=95, gid=3, sid=10, cs=5},
            new {qid=1111, cid=96, gid=3, sid=10, cs=5},
            new {qid=1111, cid=97, gid=3, sid=10, cs=5},
            new {qid=1110, cid=94, gid=4, sid=10, cs=6},
            new {qid=1110, cid=95, gid=4, sid=10, cs=4},
            new {qid=1110, cid=96, gid=4, sid=10, cs=6},
            new {qid=1110, cid=97, gid=4, sid=10, cs=4}
        };
        var avg = from item in data
                  group item by new Triplet { Value1 = item.qid, Value2 = item.gid, Value3 = item.sid } into groupedItems
                  select new
                  {
                      qid = groupedItems.Key,
                      cid1cs = groupedItems.First().cs,
                      cid2cs = groupedItems.Skip(1).First().cs,
                      cid3cs = groupedItems.Skip(2).First().cs,
                      cid4cs = groupedItems.Skip(3).First().cs,
                      avg_cs = groupedItems.Average(i => i.cs),
                      gid = groupedItems.First().gid,
                      sid = groupedItems.First().sid
                  };

首先,LINQPad是你的朋友,下载它,使用它,你会喜欢它的。它包含许多示例,并教你更多关于LINQ的知识。

关于您的分组/交叉表问题:

var data = new[] 
{
    new {qid=1110, cid=94, gid=3, sid=10, cs=6},
    new {qid=1110, cid=95, gid=3, sid=10, cs=4},
    new {qid=1110, cid=96, gid=3, sid=10, cs=6},
    new {qid=1110, cid=97, gid=3, sid=10, cs=0},
    new {qid=1111, cid=94, gid=3, sid=10, cs=5},
    new {qid=1111, cid=95, gid=3, sid=10, cs=5},
    new {qid=1111, cid=96, gid=3, sid=10, cs=5},
    new {qid=1111, cid=97, gid=3, sid=10, cs=5},
    new {qid=1110, cid=94, gid=4, sid=10, cs=6},
    new {qid=1110, cid=95, gid=4, sid=10, cs=4},
    new {qid=1110, cid=96, gid=4, sid=10, cs=6},
    new {qid=1110, cid=97, gid=4, sid=10, cs=4}
};
var query = from item in data
            group item by new { qid = item.qid, gid = item.gid, sid = item.sid } into grouped
            select new
            {
                qid = grouped.Key.qid,
                cid1cs = grouped.Where(item => item.cid == 94).Sum(item => item.cs),
                cid2cs = grouped.Where(item => item.cid == 95).Sum(item => item.cs),
                cid3cs = grouped.Where(item => item.cid == 96).Sum(item => item.cs),
                cid4cs = grouped.Where(item => item.cid == 97).Sum(item => item.cs),
                avg_cs = grouped.Average(item => item.cs),
                gid = grouped.Key.gid,
                sid = grouped.Key.sid
            };
query.Dump();

最后一行是如何在LINQPad中输出结果,这样您就可以看到您所要求的结果。

您可以使用自定义相等比较器,下面是一个示例:

  class Program
  {
    public class MyClass
    {
      public int qid { get; set; }
      public int cid { get; set; }
      public int gid { get; set; }
      public int sid { get; set; }
      public int cs { get; set; }
    }
    public class MyClassComaparer : IEqualityComparer<MyClass>
    {
      public bool Equals(MyClass x, MyClass y)
      {
        return x.qid == y.qid && x.gid == y.gid && x.sid == y.sid;
      }
      public int GetHashCode(MyClass obj)
      {
        return obj.qid;
      }
    }
    static void Main(string[] args)
    {
      var list = new List<MyClass>();
      list.Add(new MyClass() { qid = 1110, cid = 94, gid = 3, sid = 10, cs = 6 });
      list.Add(new MyClass() { qid = 1110, cid = 95, gid = 3, sid = 10, cs = 4 });
      list.Add(new MyClass() { qid = 1110, cid = 96, gid = 3, sid = 10, cs = 6 });
      list.Add(new MyClass() { qid = 1110, cid = 97, gid = 3, sid = 10, cs = 0 });
      list.Add(new MyClass() { qid = 1111, cid = 94, gid = 3, sid = 10, cs = 5 });
      list.Add(new MyClass() { qid = 1111, cid = 95, gid = 3, sid = 10, cs = 5 });
      list.Add(new MyClass() { qid = 1111, cid = 96, gid = 3, sid = 10, cs = 5 });
      list.Add(new MyClass() { qid = 1111, cid = 97, gid = 3, sid = 10, cs = 5 });
      list.Add(new MyClass() { qid = 1110, cid = 94, gid = 4, sid = 10, cs = 6 });
      list.Add(new MyClass() { qid = 1110, cid = 95, gid = 4, sid = 10, cs = 4 });
      list.Add(new MyClass() { qid = 1110, cid = 96, gid = 4, sid = 10, cs = 6 });
      list.Add(new MyClass() { qid = 1110, cid = 97, gid = 4, sid = 10, cs = 4 });
      var result = list.GroupBy(w => w, new MyClassComaparer()).Select(w => new
                  {
                    qid = w.Key.qid,
                    cid1cs = w.Where(e => e.cid == 94).Sum(e => e.cs),
                    cid2cs = w.Where(e => e.cid == 95).Sum(e => e.cs),
                    cid3cs = w.Where(e => e.cid == 96).Sum(e => e.cs),
                    cid4cs = w.Where(e => e.cid == 97).Sum(e => e.cs),                    
                    avg_cs = w.Average(i => i.cs),
                    gid = w.Key.gid,
                    sid = w.Key.sid
                  }).ToList();
      Console.ReadKey();
    }   
  }