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

时间:2013-08-12 07:54:32

标签: c# c#-4.0 linq-to-entities

我得到的实体对象如下:

{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#

有人可以帮忙吗?

提前致谢

3 个答案:

答案 0 :(得分:1)

我为你举了一个例子,但请记住,这非常容易出错!但它的确有效。如果行数少于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
                  };

答案 1 :(得分:0)

首先,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中输出结果,只是为了让您看到结果就是您所要求的。

答案 2 :(得分:0)

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

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