我有以下课程:
public class Shipment
{
public int Id { get; set; }
public List<Line> Lines { get; set; }
}
public class Line
{
public int Id { get; set; }
public List<Package> Packages { get; set; }
}
public class Package
{
public int Id { get; set; }
public List<Event> Events { get; set; }
}
public class Event
{
//irrelevant properties
}
我还有一个事件字典和packageIds:
Dictionary<Event, int> packageEvents; //already populated
我希望将字典中的所有包事件与其相应的包匹配。我编写的代码有3个复杂的foreach语句,因此具有O(n ^ 3)的复杂性。我想使用Linq将代码转换为更小的语句,并且希望也降低复杂性。
foreach (var shipment in shipments)
{
foreach (var line in shipment.Lines)
{
if (line.Packages.Any())
{
foreach (var package in line.Packages)
{
var eventsByPackage = packageEvents.Where(x => x.Value == package.Id).Select(x => x.Key);
if (package.Events == null)
{
package.Events = new List<Event>();
}
package.Events.AddRange(eventsByPackage);
}
}
}
}
我将不胜感激任何建议。提前谢谢。
答案 0 :(得分:4)
如果您需要 Linq 解决方案,建议您使用SelectMany
两次以获得展平IEnumerable<Package>
:
var packages = shipments
.SelectMany(shipment => shipment.Lines)
.SelectMany(line => line.Packages);
foreach(var package in packages) {
if (package.Events == null)
package.Events = new List<Event>();
package.Events.AddRange(packageEvents
.Where(x => x.Value == package.Id)
.Select(x => x.Key));
}
但是,您必须扫描所有软件包,这就是无法减少 O(n**3)
时间复杂度的原因;您在Linq的帮助下获得的所有内容都是可读性
答案 1 :(得分:2)
与德米特里的答案相同,但语法略有不同
var merge = new Func<Package, Package>(package =>
{
var found = packageEvents
.Where(p => p.Value == package.Id)
.Select(p => p.Key);
if (package.Events == null)
package.Events = new List<Event>();
package.Events.AddRange(found);
return package;
});
var query = from shipment in shipments
from line in shipment.Lines
from package in line.Packages
select merge(package);