[英]Ordered Distinct
I have the following 我有以下内容
IList<Project> projects = (from update in dbContext.TicketUpdates
where update.TicketUpdatesEmployeeID == Profile.EmployeeID
orderby update.TicketUpdatesEndDate descending
select update.Ticket.Project).Distinct().ToList();
I understand that Distinct()
doesn't guarantee order, but I can't reorder it afterwards because the projection loses the field I"m using to order. How can I work around this? 我明白
Distinct()
不保证顺序,但我之后无法重新排序,因为投影失去了我用来订购的字段。我该如何解决这个问题?
new solution using GroupBy 使用GroupBy的新解决方案
Update: Actually there is a much easier solution: 更新:实际上有一个更简单的解决方案:
IList<Project> projects = (from update in dbContext.TicketUpdates where update.TicketUpdatesEmployeeID == Profile.EmployeeID)
.GroupBy(tu=>tu.Ticket.Project)
.Select(group=>group.First())
.OrderByDescending(tu=>tu.TicketUpdatesEndDate)
.Select(tu=>tu.Ticket.Project)
.ToList();
(and I just saw that while I was writing this, others have posted similar answers) (我刚看到这篇文章时,其他人也发了类似的答案)
Old solution using a custom IEqualityComparer (I am not sure whether this will work with linq2sql) 使用自定义IEqualityComparer的旧解决方案 (我不确定这是否适用于linq2sql)
There is a Distinct overload that takes a custom IEqualityComparer . 有一个Distinct重载,它采用自定义IEqualityComparer 。 So do a Distinct over TicketUpdates with a custom IEqualityComparer, before projecting your data.
因此, 在投影数据之前 ,使用自定义IEqualityComparer对TicketUpdates进行区分。
The IEqualityComparer should count all TicketUpdates as equal if they have the same project. 如果IEqualityComparer具有相同的项目,则它们应将所有TicketUpdates统计为相等。 That way TicketUpdates having the same Project will be discarded.
这样,具有相同项目的TicketUpdates将被丢弃。
(note that you do not control which TicketUpdates with the same Project will be discarded. So if these TicketUpdates with the same project have different EndDates, you would need a solution involving GroupBy instead. (请注意,您无法控制哪个 TicketUpdates与同一个项目将被丢弃。因此,如果这些具有相同项目的TicketUpdates具有不同的EndDates,则需要一个涉及GroupBy的解决方案。
IList<Project> projects = (from update in dbContext.TicketUpdates where update.TicketUpdatesEmployeeID == Profile.EmployeeID)
.Distinct(new ProjectComparer())
.OrderByDescending(tu=>tu.TicketUpdatesEndDate)
.Select(tu=>tu.Ticket.Project)
.ToList();
// Your comparer should look somewhat like this
// (untested code! And I do not know all the details about your class structure)
class ProjectComparer : IEqualityComparer<TicketUpdates>
{
// Products are equal if their names and product numbers are equal.
public bool Equals(TicketUpdates x, TicketUpdates y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether projects are equal.
//(perhaps do a null check for Ticket!)
return x.Ticket.Project== y.Ticket.Project;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(TicketUpdates x)
{
//Check whether the object is null
if (Object.ReferenceEquals(x, null)) return 0;
// null check for Ticket and Project?
return x.Ticket.Project.GetHashCode();
}
}
I think your best bet is to post process to preserve ordering: 我认为您最好的选择是发布流程以保持订购:
var projects = (from update in dbContext.TicketUpdates
where update.TicketUpdatesEmployeeID == Profile.EmployeeID
orderby update.TicketUpdatesEndDate descending
select update.Ticket.Project);
var seen = new HashSet<Project>();
foreach (var project in projects)
{
if (seen.Add(project))
{
// A distinct project
}
}
Or you could abuse GroupBy
: 或者你可以滥用
GroupBy
:
var projects = dbContext.TicketUpdates
.Where(uu => uu.TicketUpdatesEmployeeID == Profile.EmployeeID)
.GroupBy(uu => uu.Ticket.Project)
.OrderByDescending(gg => gg.Max(uu => uu.TicketUpdatesEndDate))
.Select(gg => gg.Key);
By using GroupBy
across uu.Ticket.Project
each update will be grouped by their associated project. 通过在
uu.Ticket.Project
使用GroupBy
,每个更新将按其关联项目进行分组。 If you have 10 projects and 30 updates spread amongst them, you'll have 10 groups--one per project--in the output of that stage. 如果你有10个项目和30个更新,那么你将在该阶段的输出中有10个组 - 每个项目一个。 Next, we order the groups by their newest end date which preserves the descending order you were looking for.
接下来,我们按照最新的结束日期对组进行排序,保留您要查找的降序。 Finally, we select the key from each
IGrouping
which is the project. 最后,我们从每个
IGrouping
选择密钥,即项目。
You can use GroupBy operator to get unique records and then do a order by on the new recordset. 您可以使用GroupBy运算符获取唯一记录,然后在新记录集上执行订单。
var projectList = dbContext.TicketUpdates.GroupBy(p => p.TicketUpdatesEmployeeId)
.Where( r => r.TicketUpdatesEmployeeId == Profile.EmployeeId)
.Select(r => r.First())
.OrderByDesc(q => q.TicketUpdatesEndDate)
.Select(n => n.First()).Ticket.Project;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.