rick rick - 2 months ago 6
C# Question

Remove Back to Back Duplicate Entries from a List using Linq Method Syntax

I have a

List<StatusChange>
of status changes that may contain a duplicate entries, that I need to filter down removing the duplicates that happened back to back.

Hopefully a couple example lists will demonstrate what I'd like to implement using linq method syntax.

Original List with duplicate entries (Id's 2 and 3 are dups)
Id Date OldStatus NewStatus
=========================================================
1 9/28/2016 10:00:00 AM Requested Quoted
2 9/28/2016 10:15:00 AM Quoted Rejected
3 9/28/2016 10:15:01 AM Quoted Rejected
4 9/28/2016 10:30:00 AM Rejected Requested
5 9/28/2016 10:30:00 AM Requested Quoted
6 9/28/2016 10:45:00 AM Quoted Rejected
7 9/28/2016 10:50:00 AM Rejected Requested
8 9/28/2016 10:50:00 AM Requested Quoted
9 9/28/2016 10:50:00 AM Quoted Purchased


Desired List (Id 3 removed):

Id Date OldStatus NewStatus
=========================================================
1 9/28/2016 10:00:00 AM Requested Quoted
2 9/28/2016 10:15:00 AM Quoted Rejected
4 9/28/2016 10:30:00 AM Rejected Requested
5 9/28/2016 10:30:00 AM Requested Quoted
6 9/28/2016 10:45:00 AM Quoted Rejected
7 9/28/2016 10:50:00 AM Rejected Requested
8 9/28/2016 10:50:00 AM Requested Quoted
9 9/28/2016 10:50:00 AM Quoted Purchased


I thought about using
GroupBy
with
Date
,
OldStatus
and
NewStatus
, but I'm concerned that the Date will vary in seconds and I'd still like to exclude 'back to back identical' (
OldStatus
/
NewStatus
) entries.

What is an elegant solution to remove these back to back entries using linq method syntax?

Answer

You can use Aggregate: add items to an accumulating list if the current item is not equal to the last added item:

var result = list.Aggregate(new List<StatusChange>(),
    (lst, i) =>
    {
        var last = lst.LastOrDefault();
        if (last == null
                || (last.Id != i.Id 
                    && last.OldStatus != i.OldStatus
                    && last.NewStatus != i.NewStatus))
        {
            lst.Add(i);
        }
        return lst;
    });