使用 LINQ to Objects 获取 Distinct
Get Distinct using LINQ to Objects
我的数据如下图所示
所以我将它加载到一个集合中,使用匿名对象绕过创建 class
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 仅提取最近更新的不同工单。
换句话说,我应该以橙色突出显示的 3 行结束。
var myFilteredList = myList.GroupBy( //?? Totally lost... help...
如果我没有误解的话,您想要每个工作订单中的最新项目。
var latestWorkOrders = myList
.GroupBy(w => w.WorkOrderID)
.Select(g => g.OrderByDescending(w => w.LastUpdatedAt).First());
它将按 WorkOrderID
分组,并且每个分组 select 最新的项目。
以下使用 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
};
});
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();
哪个更干净。
我的数据如下图所示
所以我将它加载到一个集合中,使用匿名对象绕过创建 class
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 仅提取最近更新的不同工单。
换句话说,我应该以橙色突出显示的 3 行结束。
var myFilteredList = myList.GroupBy( //?? Totally lost... help...
如果我没有误解的话,您想要每个工作订单中的最新项目。
var latestWorkOrders = myList
.GroupBy(w => w.WorkOrderID)
.Select(g => g.OrderByDescending(w => w.LastUpdatedAt).First());
它将按 WorkOrderID
分组,并且每个分组 select 最新的项目。
以下使用 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
};
});
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();
哪个更干净。