简体   繁体   English

有序的区别

[英]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.

相关问题 具有不同记录和有序的 IQueryable - IQueryable with distinct records and ordered Linq没有命令,也没有区别 - Linq not ordered and not distinct Linq得到不同的有序元素而没有.GroupBy() - Linq get distinct ordered elements without .GroupBy() 使用Linq根据属性构造不同的有序对象 - Use Linq to construct distinct, ordered of objects based on properties 如果由包括的实体订购,如何在Linq Select Distinct中订购? - How can I order in Linq Select Distinct if ordered by an Included entity? 通过Nest Elastic Search中的降序排序获得Distinct Term - Get Distinct Term ordered by descending in Nest Elastic Search 使用独特的商品时,我无法按ID项排序 - I cant get ordered by id items when using distinct 从字符串列表中获取不同且有序的成员 - linq或hashset用于唯一哪一个更快/更适合 - Getting distinct and ordered members from a list of strings - linq or hashset for unique which one is faster / better suited 如何从多个列表中选择不同且有序的数据到通用列表中? - How can I select distinct and ordered data into a generic list from multiple lists? 如何使用 LINQ 从 DataTable 中获取不同的、有序的名称列表? - How do I get a distinct, ordered list of names from a DataTable using LINQ?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM