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()
,这样我就可以得到一份合同清单。除此之外,它工作得非常好。非常感谢。