Question

I have an object AppDetail containing 2 string properties, a name, and a version string (e.g. "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?

e.g. from these 2 items in the initial list

"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. But thats not useful, since the List.Distinct overload only accepts IEqualityComparer, not IComparer.

Any thoughts? Thanks

Was it helpful?

Solution

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. Rather, all that is needed is to know whether or not two items are equal, which is exactly why IEqualityComparer exists.

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.

OTHER TIPS

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.

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

simple query shown in pretty 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top