查询两个列表的Linq表达式
本文关键字:列表 Linq 表达式 两个 查询 | 更新日期: 2023-09-27 18:25:20
我有两种类型的对象。对象A包含id字段,对象B包含id字段和datetime字段。现在我有一个对象a的列表和一个对象B的列表。我想得到一个对象的列表,其中对象B的id等于对象a的id,同时这个对象B是对象B列表中的第一个对象,按与两个对象的一个id对应的日期字段降序排列。如何编写一个linq查询表达式来获取此列表,而不是使用循环来搜索目标对象B?提前谢谢。
如果没有你的代码,很难判断这是否有效,但你似乎想要这样的
var matchingB = listObjectB.OrderByDescending(b => b.DateTime)
.Where(b => listObjectA.Any(a => a.Id == b.Id))
.GroupBy(b => b.Id).ToList();
我强烈建议使用联接通过类似ID的字段来比较两个列表-这就是联接的作用,通常这是最有效的方法。
如果你可以假设第一个列表只有唯一的ID(就像你经常假设的ID一样),这就完成了任务:
var selected1 = listA
.Join(
listB
.GroupBy(b => b.Id)
.Select(g => g.OrderBy(b => b.Date).First()),
a => a.Id,
b => b.Id,
(a, b) => b);
如果listA中的ID大大限制了listB中的ID数量(因为分组和排序应用于这个有限的列表),那么下面的查询将产生更好的性能。
var selected2 = listA
.Join(listB, a => a.Id, b => b.Id, (a, b) => b)
.GroupBy(b => b.Id)
.Select(g => g.OrderBy(b => b.Date).First());
当listA中有重复的ID时,第二种方法有效。如果我有理由相信列表A中可能有很多重复的ID,我会使用Distinct(在ID重复的情况下,它也会修复selected1)。例如,没有EqualityComparer:
var selected3 = listA
.Select(a=>a.Id)
.Distinct()
.Join(listB, id => id, b => b.Id, (id, b) => b)
.GroupBy(b => b.Id)
.Select(g => g.OrderBy(b => b.Date).First());
在LINQ中,如果你想查询多个数据源,你可以从中获得多个,所以对于你的问题,我会做这样的事情:
internal class Program
{
private static void Main(string[] args)
{
//The below code is just me pulling some data out of the air to work with
var listOfIds = new List<ObjectA>();
var data = new List<ObjectB>();
for (var i = 0; i < 5; i++)
{
if (i % 2 == 0)
{
listOfIds.Add(new ObjectA(i));
}
data.Add(new ObjectB(i, DateTime.Now.AddDays(i)));
}
//Now we have two ILists which match the type of data you were talking about, and you simply query them like so
var datesWhereIdIsInList = (from id in listOfIds
from date in data
where id.Id == date.Id
select date).OrderByDescending(x => x.DateTime).ToList();
}
private class ObjectA
{
private readonly int _id;
public ObjectA(int id)
{
_id = id;
}
public int Id
{
get { return _id; }
}
}
private class ObjectB
{
private readonly int _id;
private readonly DateTime _dateTime;
public ObjectB(int id, DateTime dateTime)
{
_id = id;
_dateTime = dateTime;
}
public int Id
{
get { return _id; }
}
public DateTime DateTime
{
get { return _dateTime; }
}
}
}