[英]How to optimize this code
它有一个属性:字符串代码和其他10个。
公共代码是字符串列表(string [])汽车列表(Car [])filteredListOfCars是List。
for (int index = 0; index < cars.Length; index++)
{
Car car = cars[index];
if (commonCodes.Contains(car.Code))
{
filteredListOfCars.Add(car);
}
}
不幸的是,这片方法的时间太长了。
我有大约5万条记录
我怎样才能降低执行时间?
最简单的优化是将commonCodes从string[]
转换为更快的查找结构,如Dictionary<string,object>
或HashSet<string>
如果您使用.Net 3.5或更高版本。 这将减少此循环的大O复杂性,并且取决于commonCodes的大小应该使此循环执行得更快。
Jared已正确指出您可以使用HashSet
进行优化,但我还想指出整个方法是不必要的,浪费了输出列表的内存并使代码不那么清晰。
您可以将整个方法编写为:
var commonCodesLookup = new HashSet<int>(commonCodes);
var filteredCars = cars.Where(c => commonCodesLookup.Contains(c.Code));
在执行filteredCars
过滤操作将被推迟,因此,如果它的消费者只希望前10个元素,通过使用IE filteredCars.Take(10)
那么这并不需要建立整个列表(或任何列表所有)。
为了做你想做的事,我会使用Linq ToLookup方法创建一个ILookup而不是使用字典。 ToLookup特别适用于此类场景。 它基本上是对组进行索引查找。 您想按Code
对汽车进行分组。
var carCodeLookup = cars.ToLookup(car => car.Code);
carCodeLookup的创建速度很慢,但您可以根据Code
使用它来快速查找汽车。 要获取公共代码列表中的汽车列表,您可以快速查找。
var filteredCarsQuery = commonCodes.SelectMany(code => carCodeLookup[code]);
这假设您的汽车列表不会经常更改,并且您的commonCodes在查询之间是动态的。
你可以使用linq join命令,比如
var filteredListOfCars = cars.Join(commonCodes, c => c.Code, cC => cC, (car, code) => car).ToArray();
这里是linq选项的替代品(也是好主意):如果你想快速过滤,我会建议利用内置类型。 您可以创建一个DataTable
,它有两个字段,数组中汽车的id和代码(如果它们也重要,您可以添加其他10个字段)。 然后你可以在它周围创建一个DataView
并使用它的filter属性。 它在内部使用了一些非常快速的索引(我相信B树),所以你可能无法手动击败它的性能,除非你是一个算法高手,如果你是,你不会在这里问。 这取决于你正在做什么以及性能有多重要。
看起来你真正在检查的是“代码”是否常见,而不是汽车。 您可以考虑飞行重量模式,其中汽车共享代码对象的常见实例。 然后,代码对象可以具有IsCommon属性和Value属性。 然后,只要commoncodes列表发生更改,您就可以执行更新已使用的Code对象的操作。 现在,当您进行过滤时,您只需要检查每个汽车代码的IsCommon属性
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.