C# 使用LINQ降低代码复杂度
我有以下课程:C# 使用LINQ降低代码复杂度,c#,performance,linq,C#,Performance,Linq,我有以下课程: 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
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
}
公共类装运
{
公共int Id{get;set;}
公共列表行{get;set;}
}
公共班级线
{
公共int Id{get;set;}
公共列表包{get;set;}
}
公共类包
{
公共int Id{get;set;}
公共列表事件{get;set;}
}
公开课活动
{
//无关属性
}
我还有一本事件和PackageID字典:
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);
}
}
}
}
foreach(装运中的var装运)
{
foreach(装运中的var行。行)
{
if(line.Packages.Any())
{
foreach(行中的var包.Packages)
{
var eventsByPackage=packageEvents.Where(x=>x.Value==package.Id)。选择(x=>x.Key);
if(package.Events==null)
{
package.Events=新列表();
}
package.Events.AddRange(eventsByPackage);
}
}
}
}
如有任何建议,我将不胜感激。提前谢谢。如果您想要Linq解决方案,我建议使用选择many
两次,以获得展平IEnumerable
:
var packages=装运
.SelectMany(发货=>shipping.line)
.SelectMany(line=>line.Packages);
foreach(包中的var包){
if(package.Events==null)
package.Events=新列表();
package.Events.AddRange(packageEvents
.Where(x=>x.Value==package.Id)
.选择(x=>x.Key));
}
然而,你必须扫描所有的包,这就是为什么你不能降低时间复杂度的原因;在Linq的帮助下,您所能获得的只是可读性如果您想要Linq解决方案,我建议使用SelectMany
两次,以获得展平IEnumerable
:
var packages=装运
.SelectMany(发货=>shipping.line)
.SelectMany(line=>line.Packages);
foreach(包中的var包){
if(package.Events==null)
package.Events=新列表();
package.Events.AddRange(packageEvents
.Where(x=>x.Value==package.Id)
.选择(x=>x.Key));
}
然而,你必须扫描所有的包,这就是为什么你不能降低时间复杂度的原因;在Linq的帮助下,您所能获得的只是可读性与Dmitry的答案相同,但语法略有不同
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);
var merge=newfunc(包=>
{
var found=packageEvents
.Where(p=>p.Value==package.Id)
.选择(p=>p.Key);
if(package.Events==null)
package.Events=新列表();
package.Events.AddRange(已找到);
退货包装;
});
var query=来自装运中的装运
从装运中的第行开始
来自行中的包。包
选择合并(包);
与Dmitry的答案相同,但语法略有不同
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);
var merge=newfunc(包=>
{
var found=packageEvents
.Where(p=>p.Value==package.Id)
.选择(p=>p.Key);
if(package.Events==null)
package.Events=新列表();
package.Events.AddRange(已找到);
退货包装;
});
var query=来自装运中的装运
从装运中的第行开始
来自行中的包。包
选择合并(包);
如果(line.Packages.Any())
是多余的,可以安全地删除。我认为站点更适合这个问题。3嵌套循环是O(n^3)
的一个指示器(而AddRange(eventsByPackage)
将使其成为O(n^4)
),但是如果外部循环只是内部元素的分组,那么真正的复杂性仍然可以是O(n)
,其中n
是要处理的事件数。if(line.Packages.Any())
是冗余的,可以安全地删除。我认为站点更适合这个问题。3个嵌套循环是O(n^3)
(以及AddRange(eventsByPackage)
将使其成为O(n^4)
),但如果外部循环只是内部元素的分组,那么真正的复杂性仍然可以是O(n)
,而n
是要处理的事件数。奇怪的是,这被接受。此代码不起任何作用。查询
只是一个定义。为了产生结果,它必须通过foreach
ing或调用ToList()
等方式执行,这很奇怪。很多人在尝试将LINQ用于非设计用途(本例中为更新)时都会失败。你是对的,这只是查询定义,与任何查询定义一样,它也需要像你提到的那样具体化,例如通过ToList,我只是没有在我的答案中包含显而易见的内容。查看gist以获得所提供解决方案的完整概述。奇怪的是,它被接受了。此代码不起任何作用。查询
只是一个定义。为了产生结果,它必须通过foreach
ing或调用ToList()
等方式执行,这很奇怪。很多人在尝试将LINQ用于非设计用途(本例中为更新)时都会失败。你是对的,这只是查询定义,与任何查询定义一样,它也需要像你提到的那样具体化,例如通过ToList,我只是没有在我的答案中包含显而易见的内容。有关所提供解决方案的完整概述,请查看要点