繁体   English   中英

如何优化此代码

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM