Search code examples
c#listlinqduplicatesconsolidation

c# - Using LinQ to look for duplicate items in a list and updating object properties if so


I have a list Allflights of object type FLightInfo.

If an object from the list has the same flightNumber and takeofftime. I want to consolidate those entries and add their user count

Example: This is my list:

  • FlightNumber 123 Takeoff 12:00 Users 5
  • FlightNumber 256 Takeoff 3:00 Users 6
  • FlightNumber 123 Takeoff 12:00 Users 8
  • FlightNumber 651 Takeoff 5:00 Users 3

I want the output to be like:

FlightNumber 123  Takeoff 12:00 Users 13
FlightNumber 256  Takeoff 3:00  Users 6  
FlightNumber 651  Takeoff 5:00  Users 3

My source code:

struct FlightInfo
        {
            public string FlightNumber { get; set; }
            public string Takeoff_time { get; set; }
            public string Landing_time { get; set; }
            public int UserCount { get; set; }
}

static List<FlightInfo> allFlights = new List<FlightInfo>();

//I read several files using multi-threading and create a FlightInfo object   
//and add it to the allFlights list

allFlights.Add(buildFlight(FlightNumber, Origination, Destination, Takeoff_time, Landing_time, UserCount);

//This is what I need to do
//if FlightNumber && testTakeOff object attributes are the same 
// I want to consolidate those entries and add the UserCount from those entries

Solution

  • What you're looking for can be accomplished with GroupBy<TSource,TKey,TElement,TResult>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, Expression<Func<TSource,TElement>>, Expression<Func<TKey,IEnumerable<TElement>,TResult>>, IEqualityComparer<TKey>)

    Using your object definiton you could do something like this

    var consildatedFlights = allFlights.GroupBy(x => new {x.FlightNumber, x.Takeoff_time}, x => x,
                (key, vals) => ConsolidateFlightInfo(vals));
    
    foreach(var flight in consildatedFlights)
        Console.WriteLine($"FlightNumber: {flight.FlightNumber}, Takeoff Time: {flight.Takeoff_time}, User Count: {flight.UserCount}");
    
    public static FlightInfo ConsolidateFlightInfo(IEnumerable<FlightInfo> flights)
    {
        var list = flights.ToList();
        var ret = list[0];
        ret.UserCount = list.Sum(x => x.UserCount);
        return ret;
    }
    

    The first argument to .GroupBy specifies an anonymous type describing describing the properties you want to group by. The second item specifies what you want in your results lists (one per group). In this case we want the entire flight info object. The third parameter specifies how you want to transform each grouping. In this case we pass each set of grouped flights to a method that sums UserCount and returns a single FlightInfo with that summed value.