0

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

4

3 回答 3

1

没有您的代码,很难判断这是否可行,但似乎您想要这样的东西

var matchingB = listObjectB.OrderByDescending(b => b.DateTime)
           .Where(b => listObjectA.Any(a => a.Id == b.Id))
           .GroupBy(b => b.Id).ToList();
于 2013-07-27T16:08:29.860 回答
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 中的 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 时,第二种方法有效。如果我有理由相信 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());
于 2013-07-27T22:27:30.127 回答
0

在 LINQ 中,如果你想查询多个数据源,你可以有多个from ,所以对于你的问题,我会做这样的事情:

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; }
        }
    }
}
于 2013-07-27T13:23:22.533 回答