2013-07-27 115 views
0

我有两种类型的对象。对象A包含一个id字段,对象B包含一个id字段和一个datetime字段。现在我有对象A的列表和对象B的列表。我想获得对象B的列表,其中对象B的ID等于对象A的ID,同时该对象B是第一个对象在对象B列表中按照与两个对象的一个​​id相对应的日期字段降序排列。我怎么能写一个单一的LINQ查询表达式来获得这个列表,而不是使用循环来循环搜索目标对象B?提前致谢。Linq表达式查询两个列表

+0

您可以发布您目前的代码吗? – JMK

回答

0

在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; } 
     } 
    } 
} 
+0

谢谢JMK。事实上,我需要一个对象B的列表,它是对象B列表中的第一个对象,这些对象是由对应于对象A和对象B的一个id的日期字段降序排列的。在我的情况下,考虑对象A中的一个id,具有相同标识但日期时间不同的多个对象B.所以目标列表总是包含第一个对象B按照日期时间降序排列,对应于一个对象A中的一个ID。 – user1196284

+0

@ user1196284我认为在这个答案和其他人之间,你应该有足够的工作,祝你好运:) – JMK

1

没有你的代码很难告诉这是否会工作,但好像你希望是这样的

var matchingB = listObjectB.OrderByDescending(b => b.DateTime) 
      .Where(b => listObjectA.Any(a => a.Id == b.Id)) 
      .GroupBy(b => b.Id).ToList(); 
1

我强烈建议使用加入通过一个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中大大限制了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时,第二种方法有效。如果我有理由相信listA中可能有许多重复的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()); 
+0

谢谢,口齿不清。我忘了提及列表A中的ID是不同的,并且在列表B中可能没有项目或者与列表A中的相同ID相对应的至少一个或多于一个项目。 – user1196284

+0

@ user1196284然后select1和select2(以及select3也)会为你工作。 **按照您所描述的方式加入**处理没有匹配ID的案例(不需要使用.Any(),效率会更低)。 (顺便说一下,如果你需要不同的行为来匹配没有匹配的ID,请查看**左右连接**;仍然:总是通过连接ID来比较两个列表) – lisp