C# 筛选列表中的第一项<;合同>;使用LINQ

C# 筛选列表中的第一项<;合同>;使用LINQ,c#,linq,C#,Linq,我有一个var contracts=newlist()这是在特定时间范围内编写的所有合同的主列表。合同对象如下所示: public class Contract { public int Id { get; set; } public int CompanyId { get; set; } public string CompanyName { get; set; } public DateTime ContractDate { get; set; } public

我有一个
var contracts=newlist()这是在特定时间范围内编写的所有合同的主列表。合同对象如下所示:

public class Contract
{
   public int Id { get; set; }
   public int CompanyId { get; set; }
   public string CompanyName { get; set; }
   public DateTime ContractDate { get; set; }
   public decimal Amount { get; set; }
}
主列表可能包含也可能不包含同一公司的多个合同,因此并非所有的
公司ID都是唯一的

我的任务是制作:

  • 所有的“第一”合同,也就是说,如果一家公司只有一份合同,它就会进入我的产出。如果同一家公司有多份合同,那么我会选择最小/最早的
    ContractDate
  • 我还需要生成一个与第一个相反的列表,也就是说,我需要在输出中包含所有第二个、第三个等合同。如果与一家公司只有一份合同,我会将其包括在我的输出中,但如果我与一家公司有多份合同,我会跳过第一份合同,将其余合同包括在我的输出中

  • 我可以使用
    foreach
    循环来实现这一点,但我想看看如何使用
    LINQ

    产生相同的结果,直到现在,我已经完成了第一个循环,尽管不像预期的那么容易

    var results =
                    from kvp in list
                    group kvp by kvp.CompanyId into g
                    select new
                    {
                        Group = g,
                        Max = g.Max(kvp => kvp.ContractDate),
                    } into ag
                    from x in ag.Group
                    where x.ContractDate == ag.Max
                    select new
                    {
                        CompanyId = x.CompanyId,
                        Amount = x.Amount,
                        ContractDate = ag.Max,
                        CompanyName = x.CompanyName
                    };
    
    检验,

    public static void Main()
    {
        var c1 = new Contract { Id = 1, CompanyId = 1000, CompanyName = "ABC", Amount = 1337, ContractDate = new DateTime(2000, 12, 30)};
        var c2 = new Contract { Id = 2, CompanyId = 1001, CompanyName = "XYZ", Amount = 97, ContractDate = new DateTime(2001, 12, 30)};
        var c3 = new Contract { Id = 3, CompanyId = 2222, CompanyName = "iQuest", Amount = -999, ContractDate = new DateTime(1994, 1, 1)};
        var c4 = new Contract { Id = 4, CompanyId = 2222, CompanyName = "iQuest", Amount = -999, ContractDate = new DateTime(2020, 1, 1)};
    
        var list = new List<Contract> { c1, c2, c3, c4 };
    
        var results =
        from kvp in list
        group kvp by kvp.CompanyId into g
        select new
        {
          Group = g,
          Max = g.Max(kvp => kvp.ContractDate),
        } into ag
        from x in ag.Group
        where x.ContractDate == ag.Max
        select new
        {
          CompanyId = x.CompanyId,
          Amount = x.Amount,
          ContractDate = ag.Max,
          CompanyName = x.CompanyName
        };
    }
    
    // Define other methods, classes and namespaces here
    public class Contract
    {
        public int Id { get; set; }
        public int CompanyId { get; set; }
        public string CompanyName { get; set; }
        public DateTime ContractDate { get; set; }
        public decimal Amount { get; set; }
    }
    
    publicstaticvoidmain()
    {
    var c1=新合同{Id=1,CompanyId=1000,CompanyName=“ABC”,金额=1337,合同日期=newdatetime(2000,12,30)};
    var c2=新合同{Id=2,CompanyId=1001,CompanyName=“XYZ”,金额=97,合同日期=new DateTime(2001,12,30)};
    var c3=新合同{Id=3,CompanyId=2222,CompanyName=“iQuest”,金额=-999,合同日期=新日期时间(1994,1,1)};
    var c4=新合同{Id=4,CompanyId=2222,CompanyName=“iQuest”,金额=-999,合同日期=新日期时间(2020,1,1)};
    var list=新列表{c1,c2,c3,c4};
    var结果=
    从列表中的kvp
    按kvp.CompanyId将kvp分组为g
    选择新的
    {
    组=g,
    Max=g.Max(kvp=>kvp.ContractDate),
    }进入ag
    来自ag集团的x
    其中x.ContractDate==ag.Max
    选择新的
    {
    CompanyId=x.CompanyId,
    金额=x.金额,
    合同日期=ag.Max,
    CompanyName=x.CompanyName
    };
    }
    //在此处定义其他方法、类和名称空间
    公共类合同
    {
    公共int Id{get;set;}
    public int CompanyId{get;set;}
    公共字符串CompanyName{get;set;}
    公共日期时间契约日期{get;set;}
    公共十进制数{get;set;}
    }
    
    对于第一个,我相信这样就可以了

    contracts
        .GroupBy(c => c.CompanyId)
        .Select(c => c.OrderBy(o => o.ContractDate).First());
    
    对于第二个问题:

    contracts
        .GroupBy(c => c.CompanyId)
        .Select(c => c.OrderBy(o => o.ContractDate).Skip(c.Count() == 1 ? 0 : 1))
        .SelectMany(c => c)
    

    分享您可以使用
    foreach
    loop执行的代码,以获得某种最小的可复制性。请不要回答提问者要求您为他们编写代码的问题。这会助长懒惰和低质量的问题。@IanKemp我知道。我只是把这个问题看作是提高我linq技能的一种练习。比我更好的是,给魔鬼应得的,+1唯一的改进是在末尾添加
    .ToList()
    ,这样我就可以得到一份合同清单。除此之外,它工作得非常好。非常感谢。