我有一个列表对象类型为 FLightInfo.
如果列表中的物体具有相同的航班号和起飞时间。 我想合并这些条目并添加其用户计数
示例:这是我的列表:
- 航班号 123 起飞 12:00 用户 5
- 航班号 256 起飞 3:00 用户 6
- 航班号 123 起飞 12:00 用户 8
- 航班号 651 起飞 5:00 用户 3
我希望输出如下所示:
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
你正在寻找的东西可以用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
变成了一个类,并根据 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 类来照顾
- 使用 Lock 语句防止任何多线程问题
- 合并条目
飞行管理器
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);
POCO(数据对象(
如果删除构造函数,则还有另一种语法可以初始化FlightInfo
。
var flightInfo = new FlightInfo()
{
Origination = origination,
Destination = destination,
// ...
}
但是构造函数明确了您的意图,即用户必须提前提供所有数据。如果您使用的是序列化库,这可能是不可能的。