I have a list which contains duplicate item values (by ID), but with a different (or possibly equal) priority. Duplicate items with same or lower priority should be removed from the list.
For example:
var items = new {
new { Id=2, Priority=3 },
new { Id=4, Priority=4 },
new { Id=1, Priority=4 },
new { Id=2, Priority=5 },
new { Id=4, Priority=4 }
};
RemoveDuplicates(items);
// items should now contain distinct values,
// with highest possible priority
var items = new {
new { Id=1, Priority=4 }, // this one was unique
new { Id=2, Priority=5 }, // this one was duplicate with higher priority
new { Id=4, Priority=4 }, // this one was duplicate with same priority
};
Is it possible to do this using LINQ? I know I could sort the list by ID and then check adjacent items, but just wanted to check if this is possible.
(update: input values are not necessarily grouped by IDs)
LINQ Distinct is not that smart when it comes to custom objects. All it does is look at your list and see that it has two different objects (it doesn't care that they have the same values for the member fields). One workaround is to implement the IEquatable interface as shown here.
If you want to return distinct elements from sequences of objects of some custom data type, you have to implement the IEquatable<T> generic interface in the class. The following code example shows how to implement this interface in a custom data type and provide GetHashCode and Equals methods.
var items = new[] {
new { Id=2, Priority=3 },
new { Id=2, Priority=5 },
new { Id=1, Priority=4 },
new { Id=4, Priority=4 },
new { Id=4, Priority=4 }
};
var deduped = items
.GroupBy(item => item.Id)
.Select(group => group.OrderByDescending(item => item.Priority).First())
.OrderBy(item => item.Id);
The Distinct Extension Method returns the distinct elements from a sequence. You can provide an IEqualityComparer<TSource> to determine when two elements are equal. However, the method does not allow you to choose which of the two equal elements is used.
You can use the GroupBy Extension Method to group the list by ID and then select the element with the highest priority from each group:
var query = items.GroupBy(item => item.Id)
.Select(g => g.MaxBy(item => item.Priority))
.OrderBy(item => item.Id);
using MaxBy from MoreLINQ.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With