简体   繁体   English

在List中获取具有最高属性值的不同项

[英]get distinct item in List with highest value in property

I have an object AppDetail containing 2 string properties, a name, and a version string (eg "1.0.0") 我有一个对象AppDetail包含2个字符串属性,一个名称和一个版本字符串(例如“1.0.0”)

Given a List< AppDetail > that contains duplicates of the same name but different version strings, how do I create a List with unique names, and highest versions? 如果List <AppDetail>包含相同名称但不同版本字符串的重复项,如何创建具有唯一名称和最高版本的List?

eg from these 2 items in the initial list 例如,从初始列表中的这2个项目开始

"name", "1.0.1"
"name", "1.1.0"

I want the unique items list to contain only the second item, since it has the highest version. 我希望唯一项目列表仅包含第二个项目,因为它具有最高版本。

To compare versions I need to create an IComparer that creates Version objects and then to use the version.CompareTo(version) method. 要比较版本,我需要创建一个IComparer来创建Version对象,然后使用version.CompareTo(version)方法。 But thats not useful, since the List.Distinct overload only accepts IEqualityComparer, not IComparer. 但这没用 ,因为List.Distinct重载只接受IEqualityComparer,而不接受IComparer。

Any thoughts? 有什么想法吗? Thanks 谢谢

It makes sense that List.Distinct() doesn't accept an IComparer , since determining if two items are distinct does not require knowing if one item would precede another (or visa versa,) which is the purpose of the IComparer interface. 有意义的是List.Distinct()不接受IComparer ,因为确定两个项是否是不同的并不需要知道一个项是否先于另一项(反之亦然),这是IComparer接口的目的。 Rather, all that is needed is to know whether or not two items are equal , which is exactly why IEqualityComparer exists. 相反,所需要的只是知道两个项是否相等 ,这正是IEqualityComparer存在的原因。

You don't need to implement either, though. 但是,您也不需要实现。 You can create a query that selects the appropriate items, by first grouping all the items by name, and then selecting only the highest version number from each group: 您可以创建一个选择相应项目的查询,首先按名称对所有项目进行分组,然后仅从每个组中选择最高版本号:

var namesWithHighestVersion = 
    appDetailList
        .GroupBy(x => x.Name)
        .Select(x => new AppDetail { 
                         Name = x.Key,
                         Version = x.Max(x => new Version(x.Version)).ToString()
                        })
        .ToList();

Note that this creates a new list, rather than updating the old list. 请注意,这会创建一个新列表,而不是更新旧列表。

Also, you could simplify everything somewhat by making the original type use a Version , instead of a string. 此外,您可以通过使原始类型使用Version而不是字符串来简化一切。

simple query shown in pretty sql: 简单的查询显示在漂亮的SQL:

var aDetail  =  from a in appdetail
                group a by a.name into aGroup
                orderby a.version descending
                select new 
                    {name = aGroup.name, 
                     version = aGroup.Max(version)}.ToList();

The grouping will naturally make the query distinct 分组自然会使查询区别开来

Sorry about earlier in using MaxBy, including the following project found here: "more linq" made me think of MaxBy instinctively. 很抱歉早些时候使用MaxBy,包括以下项目: “more linq”让我本能地想起MaxBy。

This solution is similar to dlev's answer, however, it will return the instance of the one with the highest version, instead of creating a new instance with the same values. 此解决方案类似于dlev的答案,但是,它将返回具有最高版本的实例,而不是创建具有相同值的新实例。

var namesWithHighestVersion = 
    appDetailList
        .GroupBy(a => a.Name)
        .Select(g => g.OrderByDescending(a => a.Version).First())
        .ToList();

var latestVersion =(来自appDetailList中的a选择a.Version).Max();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM