分组,加起来然后用linq排序

时间:2017-05-21 19:59:40

标签: c# entity-framework linq razor viewbag

我有3个牌桌,赛车和赛车手。

public partial class Driver
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Driver()
    {
        this.DriverRaces = new HashSet<DriverRace>();
    }

    public int DriverID { get; set; }

    [DisplayName("Name")]
    public string DriverName { get; set; }

    [DisplayName("Number")]
    public string DriverNumber { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<DriverRace> DriverRaces { get; set; }
}

public partial class DriverRace
{
    public int DriverRaceID { get; set; }

    public int Points { get; set; }

    [DisplayName("Driver")]
    public Nullable<int> Driver_DriverID { get; set; }

    [DisplayName("Race")]
    public Nullable<int> Race_RaceID { get; set; }

    public virtual Driver Driver { get; set; }

    public virtual Race Race { get; set; }
}

public partial class Race
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Race()
    {
        this.DriverRaces = new HashSet<DriverRace>();
    }
    public int RaceID { get; set; }

    public System.DateTime RaceDate { get; set; }

    [DisplayName("Name")]
    public string RaceName { get; set; }

    [DisplayName("Class")]
    public string RaceClass { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<DriverRace> DriverRaces { get; set; }
}

有5类比赛,一个驱动程序可以在多个类中,并且可以参加多个比赛。我正在尝试写一个linq语句来获得每个班级的前5名车手,以及他们在该班级中每场比赛的总得分总和。

我知道如何选择所有菜鸟司机并获得他们的名字和积分

var drivers = DriverRaces.Where(d=>d.Points > 0 && d.Race.RaceClass == "Rookie");
foreach (var driver in drivers){
    Console.WriteLine("Driver Name is {0} points is {1}", driver.Driver.DriverName, driver.Points);
}

这可能会返回类似

的内容
Driver Name is Alexander points is 100
Driver Name is Mady points is 99
Driver Name is Blake points is 98
Driver Name is Alexander points is 100
Driver Name is Mady points is 99
Driver Name is Tom points is 98

但我想要它显示

Driver Name is Alexander points is 200
Driver Name is Mady points is 198
Driver Name is Blake points is 98
Driver Name is Tom points is 98

我需要帮助添加每个驱动程序总计,然后对它们进行排序。

1 个答案:

答案 0 :(得分:1)

要实现目标,您需要汇总这些结果。有两种方法使用Aggregate其他SelectAggregate更高效,Select更清洁。

我添加了一个小例子来表明行为:

class Program
{
    static void Main(string[] args)
    {
        List<Driver> driversFirstTable = new List<Driver>()
        {
            new Driver
            {
                DriverName = "John", DriverRaces = new Collection<DriverRace>
                {
                    new DriverRace { Points = 99, Category = "Rookie" },
                    new DriverRace { Points = 100, Category = "Rookie" },
                    new DriverRace { Points = 10, Category = "Mid" },
                    new DriverRace { Points = 99, Category = "Pro" },
                }
            },

            new Driver
            {
                DriverName = "Jack", DriverRaces = new Collection<DriverRace>
                {
                    new DriverRace { Points = 100, Category = "Rookie" },
                    new DriverRace { Points = 98, Category = "Rookie" },
                    new DriverRace { Points = 66, Category = "Mid" },
                    new DriverRace { Points = 100, Category = "Pro" },
                }
            },
            new Driver
            {
                DriverName = "Richard", DriverRaces = new Collection<DriverRace>
                {
                    new DriverRace { Points = 98, Category = "Rookie" },
                    new DriverRace { Points = 99, Category = "Rookie" },
                    new DriverRace { Points = 62, Category = "Mid" },
                    new DriverRace { Points = 98, Category = "Pro" },
                }
            },
            new Driver
            {
                DriverName = "Will", DriverRaces = new Collection<DriverRace>
                {
                    new DriverRace { Points = 97, Category = "Rookie" },
                    new DriverRace { Points = 97, Category = "Rookie" },
                    new DriverRace { Points = 61, Category = "Mid" },
                    new DriverRace { Points = 97, Category = "Pro" },
                }
            }
        };


        var rookieTop = driversFirstTable
            .Select(x => new DriverAggregated { Category = "Rookie", DriverName = x.DriverName, TotalPoints = x.DriverRaces.Where(y => y.Category == "Rookie").Sum(y => y.Points) })
            .OrderByDescending(x => x.TotalPoints)
            .Take(3);
        // Will is not in the list
        foreach (var driver in rookieTop)
        {
            Console.WriteLine($"Driver - {driver.DriverName} gathered {driver.TotalPoints} points.");
        }
        Console.Read();
    }
}

class DriverAggregated
{
    public string DriverName { get; set; }
    public int TotalPoints { get; set; }
    public string Category { get; set; }
}

public class Driver
{
    public string DriverName { get; set; }

    public virtual ICollection<DriverRace> DriverRaces { get; set; }
}

public class DriverRace
{
    public int Points { get; set; }
    public string Category { get; set; }
}

修改

另一种方法可能是使用聚合函数不是很漂亮但性能更高:

        var topRookie = driversFirstTable.Select(x => x.DriverRaces.Aggregate(new DriverAggregated() { Category = "Rookie", DriverName = x.DriverName }, (seed, race) =>
          {
              if (race.Category == seed.Category)
                  seed.TotalPoints += race.Points;
              return seed;
          }))
         .OrderByDescending(x => x.TotalPoints)
         .Take(3);