C# 用于查询两个列表的Linq表达式

C# 用于查询两个列表的Linq表达式,c#,linq,C#,Linq,我有两种类型的对象。对象A包含id字段,对象B包含id字段和日期时间字段。现在我有一个对象a的列表和一个对象B的列表。我想得到一个对象B的列表,其中对象B的id等于对象a的id,同时这个对象B是对象B列表中的第一个对象,按日期字段降序排列,对应于两个对象的一个id。如何编写一个linq查询表达式来获取此列表,而不是使用循环来搜索目标对象B?提前感谢。在LINQ中,如果要查询多个数据源,您可以从中获得多个,因此对于您的问题,我将执行以下操作: internal class Program {

我有两种类型的对象。对象A包含id字段,对象B包含id字段和日期时间字段。现在我有一个对象a的列表和一个对象B的列表。我想得到一个对象B的列表,其中对象B的id等于对象a的id,同时这个对象B是对象B列表中的第一个对象,按日期字段降序排列,对应于两个对象的一个id。如何编写一个linq查询表达式来获取此列表,而不是使用循环来搜索目标对象B?提前感谢。

在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; }
        }
    }
}
内部类程序
{
私有静态void Main(字符串[]args)
{
//下面的代码只是我从空中提取一些数据来处理
var listOfIds=新列表();
var data=新列表();
对于(变量i=0;i<5;i++)
{
如果(i%2==0)
{
添加(新对象a(i));
}
Add(newobjectb(i,DateTime.Now.AddDays(i));
}
//现在我们有两个IList,它们与您刚才讨论的数据类型相匹配,您只需像这样查询它们
var DATESWHEREIDSINLIST=(来自listOfIds中的id
数据中的起始日期
其中id.id==date.id
选择date).OrderByDescending(x=>x.DateTime).ToList();
}
私有类对象
{
私有只读int_id;
公共对象A(内部id)
{
_id=id;
}
公共整数Id
{
获取{return\u id;}
}
}
私有类对象B
{
私有只读int_id;
私有只读日期时间\u DateTime;
公共对象B(int-id,DateTime-DateTime)
{
_id=id;
_dateTime=dateTime;
}
公共整数Id
{
获取{return\u id;}
}
公共日期时间日期时间
{
获取{return\u dateTime;}
}
}
}

如果没有你的代码,很难判断这是否有效,但似乎你想要这样的东西

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数量(因为分组和排序应用于这个有限的列表),那么下面的查询将产生更好的性能

当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());

你能发布你目前拥有的代码吗?谢谢JMK。实际上,我需要一个对象B的列表,它是对象B列表中的第一个对象,按对象a和对象B的一个id对应的日期字段降序排列。在我的例子中,考虑到对象a中的一个id,可以有多个具有相同id但不同日期时间的对象B。因此,目标列表始终包含第一个对象B,该对象B按日期时间降序,对应于一个对象A中的一个id。@user1196284我认为在这个答案和其他答案之间,您应该有足够的时间来处理,祝您好运:)谢谢,lisp。我忘了提到列表A中的id是不同的,在列表B中可能没有项目,或者至少有一个或多个项目对应于列表A中的同一id。@user1196284然后选择1和选择2(以及选择3)将适用于您。join完全按照您描述的方式处理不匹配ID的情况(无需使用.Any(),效率要低得多)。(顺便说一句,如果您需要对不匹配的ID使用不同的行为,请查看左联接和右联接;不过:始终使用联接比较两个按ID列出的列表)
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());