c# - 使用 LinQ 查找列表中的重复项并在出现时更新对象属性
c# - Using LinQ to look for duplicate items in a list and updating object properties if so
我有一个 list 对象类型为 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
我把你的 FlightInfo
改成 class 并根据 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 来处理
- 使用锁定语句防止任何多线程问题
- 合并条目
飞行管理器
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,
// ...
}
但是构造函数让你的意图很明确,用户必须提前提供所有数据。如果您使用的是序列化库,这可能是不可能的。
来完成
使用你的对象定义你可以做这样的事情
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
和 returns 与该总和值相加 FlightInfo
。
我有一个 list 对象类型为 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
我把你的 FlightInfo
改成 class 并根据 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 来处理
- 使用锁定语句防止任何多线程问题
- 合并条目
飞行管理器
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,
// ...
}
但是构造函数让你的意图很明确,用户必须提前提供所有数据。如果您使用的是序列化库,这可能是不可能的。
使用你的对象定义你可以做这样的事情
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
和 returns 与该总和值相加 FlightInfo
。