2016-07-17 36 views
0

我有一个类是一个复合类,由各种来源的统计类组成。综合类根据统计类中的排序和排名属性获得“总分”。复合类可重复使用的匿名排名函数

例如,统计类可以如下:

public class StatsTypeA 
{ 
    public int PropAX { get; set; } 
    public int PropAXPoints { get; set; } 

    public int PropAY { get; set; } 
    public int PropAYPoints { get; set; } 
} 

和复合类是这样的例子:

class CompositeType 
{ 
    public StatsTypeA StatsA { get; set; } 
    public StatsTypeB StatsB { get; set; } 
    public int Id { get; set; } 
    public int TotalPoints 
    { 
     get 
     { 
      return StatsA.PropAXPoints + StatsA.PropAYPoints +     StatsB.PropBXPoints + StatsB.PropBYPoints; 
     } 
    } 
} 

在主类,会有的复合列表类中的每个属性都具有值:

List<CompositeType> participants = new List<CompositeType>(); 

我想要吸着吨和排名他们,并可以用蛮力这样做,但不能找出一种方法不重复一堆代码。举例来说,一个属性可以归类,并记为:

var statsX = composites.GroupBy(s => s.StatsA.PropAX, 
          s => s.Id, 
          (key, group) => (new 
          { 
           Stats = key, 
           Participants = group.ToList() 
          })) 
        .OrderBy(s => s.Stats); 
int points = 0; 
foreach (var statGroup in statsX) 
{ 
    var maxPoints = points + statGroup.Participants.Count * 2 - 2; 
    var thisPoints = (points + maxPoints)/2; 
    foreach (var id in statGroup.Participants) 
    { 
     composites.Single(data => data.Id == id).StatsA.PropAXPoints = points; 
    } 
    points = maxPoints + 2; 
} 

有没有一种方法,使使用匿名类型从上面的LINQ语句可重复使用的匿名函数?换句话说,我怎样才能有一个函数/扩展方法来对每个单独的统计属性进行排名?

+0

如果您愿意放弃匿名类型,则可以使用通用扩展方法和包含统计信息和参与者的类。 – Warty

回答

1

这是我想出了一个通用的方法:

Action<IEnumerable<CompositeType>, Func<CompositeType, int>, Action<CompositeType, int>> compute = 
    (cs, f, a) => 
    { 
     var stats = 
      from c in cs 
      group c by f(c) into gs 
      orderby gs.Key 
      select new 
      { 
       Stats = gs.Key, 
       Participants = gs.ToList() 
      }; 

     stats.Aggregate(0, (points, statGroup) => 
     { 
      var maxPoints = points + statGroup.Participants.Count * 2 - 2; 
      var avgPoints = (points + maxPoints)/2; 
      statGroup.Participants.ForEach(c => a(c, avgPoints)); 
      return maxPoints + 2; 
     }); 
    }; 

现在,我可以这样调用:

compute(composites, c => c.StatsA.PropAX, (c, p) => c.StatsA.PropAXPoints = p); 
compute(composites, c => c.StatsA.PropAY, (c, p) => c.StatsA.PropAYPoints = p); 
compute(composites, c => c.StatsB.PropBX, (c, p) => c.StatsB.PropBXPoints = p); 
compute(composites, c => c.StatsB.PropBY, (c, p) => c.StatsB.PropBYPoints = p); 

是,你是什么之后?

+0

美丽。谢谢。 –