У меня есть список Allflights типа объекта FLightInfo.
Если объект из списка имеет одинаковый номер рейса и время взлета. Я хочу объединить эти записи и добавить их количество пользователей
Пример: Это мой список:
Я хочу, чтобы выход выглядел так:
FlightNumber 123 Takeoff 12:00 Users 13
FlightNumber 256 Takeoff 3:00 Users 6
FlightNumber 651 Takeoff 5:00 Users 3
Мой исходный код:
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
Не могли бы вы добавить несколько простых данных и ожидаемого результата?





Я сделал ваш FlightInfo классом и переименовал некоторые свойства в соответствии со стилями кода C#. Также я добавил конструктор, который принимает данные.
class FlightInfo
{
public FlightInfo(string flightNumber, string origination, ...)
{
FlightNumber = flightNumber;
Origination = origination;
// ...
}
public string FlightNumber { get; set; }
public string Origination { get; set; }
public string Destination { get; set; }
public string TakeoffTime { get; set; }
public string LandingTime { get; set; }
public int UserCount { get; set; }
}
Мы добавляем класс FlightManager, который заботится о
class FlightManager
{
private object _lock = new object();
private List<FlightInfo> _flights = new List<FlightInfo>();
public void Add(FlightInfo info)
{
lock(_lock)
{
// look for existing flights
var existing = _flights.FirstOrDefault(f =>
{
return f.FlightNumber == info.FlightNumber
&& f.TakeoffTime == info.TakeoffTime;
});
// FirstOrDefault will return null if none found
if (existing == null)
{
// add as new flight
_flights.Add(info);
}
else
{
// add passenger count
existing.UserCount += info.UserCount;
}
}
}
}
static FlightManager Manager = new FlightManager();
allFlights.Add(new FlightInfo(FlightNumber, Origination, Destination, TakeoffTime, LandingTime, UserCount);
Существует альтернативный синтаксис для инициализации вашего FlightInfo, если вы отбрасываете конструктор.
var flightInfo = new FlightInfo()
{
Origination = origination,
Destination = destination,
// ...
}
но конструктор проясняет ваше намерение, что пользователь должен предоставить все данные заранее. Однако, если вы используете библиотеку сериализации, это может быть невозможно.
Есть еще несколько методов, например, вы можете использовать ConcurrentDictionary и его метод AddOrUpdate для этого.
То, что вы ищете, может быть выполнено с помощью GroupBy<TSource,TKey,TElement,TResult>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, Expression<Func<TSource,TElement>>, Expression<Func<TKey,IEnumerable<TElement>,TResult>>, IEqualityComparer<TKey>)
Используя определение вашего объекта, вы можете сделать что-то вроде этого
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;
}
Первый аргумент .GroupBy указывает анонимный тип, описывающий свойства, по которым вы хотите группировать. Второй элемент указывает, что вы хотите в списках результатов (по одному на группу). В этом случае нам нужен объект информации о полете целиком. Третий параметр указывает, как вы хотите преобразовать каждую группу. В этом случае мы передаем каждый набор сгруппированных рейсов в метод, который суммирует UserCount и возвращает один FlightInfo с этим суммированным значением.
Немного поздно, но спасибо вам за это !! это сработало отлично. Я просто пометил ваш ответ как ответ :)
Можете попробовать перед добавлением проверить? Как бы Вы это сделали? Вы можете создать класс, который принимает объекты FlightInfo, а затем выполняет проверку / консолидацию. Если вы действительно добавляете из нескольких потоков, вам следует рассмотреть возможность использования оператора
lock. Бонус: ваш новый класс может применить эту блокировку!