【问题标题】:Get Distinct using LINQ to Objects使用 LINQ to Objects 获得不同
【发布时间】:2019-03-20 11:58:33
【问题描述】:

我的数据如下图

所以我将它加载到一个集合中,使用匿名对象绕过创建一个类

List<dynamic> myList = new List<dynamic>()
        {
            new {
                WorkOrderID = 40001,
                LastUpdatedAt = DateTime.Parse("2018-10-02"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40001,
                LastUpdatedAt = DateTime.Parse("2017-06-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40002,
                LastUpdatedAt = DateTime.Parse("2018-07-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40003,
                LastUpdatedAt = DateTime.Parse("2018-09-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40001,
                LastUpdatedAt = DateTime.Parse("2016-01-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
            new {
                WorkOrderID = 40002,
                LastUpdatedAt = DateTime.Parse("2016-12-01"),
                Col3 = "abc",
                Col4 = "xyz"
            },
        };

如何使用 Linq-to-Objects 仅提取最近更新的 DISTINCT WorkOrders。

换句话说,我应该以橙色突出显示的 3 行结束。

var myFilteredList = myList.GroupBy( //?? 完全丢失了...帮助...

【问题讨论】:

  • 如果您能明确说明您所期望的结果,那就太好了。

标签: c# linq linq-to-objects


【解决方案1】:

如果我没有误会,您需要每个工作订单的最新项目。

var latestWorkOrders = myList
    .GroupBy(w => w.WorkOrderID)
    .Select(g => g.OrderByDescending(w => w.LastUpdatedAt).First());

它将按WorkOrderID 分组,并为每个分组选择最新的项目。

【讨论】:

  • 您的左侧 latestWorkOrders 是 LINQ 查询,而不是最终结果?即我仍然需要做 var finalList = latestWorkOrders.ToList()
  • 对不起,是的。这是一个 LINQ 查询,所以你需要.ToList()。
【解决方案2】:

以下使用GroupBy 重载,因此可以在同一个调用中完成元素选择并将它们转换为强类型匿名对象。

var myFilteredList = myList
    .GroupBy(_ => (int)_.WorkOrderID, (k, g) =>
    {
        var recent = g.OrderByDescending(_ => _.LastUpdatedAt).First();
        return new
        {
            WorkOrderID = k,
            LastUpdatedAt = (DateTime)recent.LastUpdatedAt,
            Col3 = (string)recent.Col3,
            Col4 = (string)recent.Col4
        };
    });

Fiddle

【讨论】:

  • 感谢您的回答,它确实有效,但我选择了第一个正确的回复;您的左侧是一个 linq 查询,而不是最终列表,最后缺少一个 .ToList() 转换?
【解决方案3】:
List<dynamic> list = myList
               .GroupBy(a => a.WorkOrderID )
               .OrderByDescending(b => b.LastUpdatedAt)
               .Select(g => g.FirstOrDefault())
               .ToList();

foreach (var p in list)
{
    Console.WriteLine(p.WorkOrderID + " : " + p.Col3);
}

就个人而言,动态不是一个好的选择。如果你有一个对象,那么你可以在对象上实现Equals 和GetHashCode。这样你就可以做到:

var list = myList.Select(o => new { o.WorkOrderID, ... })
                                       .Distinct();

这样更干净。

【讨论】:

  • IGrouping 不包含 LastUpdatedAt 的定义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-03
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
相关资源
最近更新 更多