如何优化此代码

时间:2010-03-17 16:16:17

标签: c# performance

它有一个属性: 字符串代码 和另外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);
    }
}

不幸的是,这段方法的时间过长了。

我有大约50k的记录

如何降低执行时间??

6 个答案:

答案 0 :(得分:20)

最简单的优化是,如果您使用.Net 3.5或更高版本,则将commonCodes从string[]转换为更快的查找结构,例如Dictionary<string,object>HashSet<string>。这将减少此循环的大O复杂性,并且取决于commonCodes的大小应该使此循环执行得更快。

答案 1 :(得分:16)

Jared正确地指出你可以用HashSet来优化它,但我还想指出整个方法是不必要的,浪费了输出列表的内存并使代码不那么清晰。 / p>

您可以将整个方法编写为:

var commonCodesLookup = new HashSet<int>(commonCodes);
var filteredCars = cars.Where(c => commonCodesLookup.Contains(c.Code));

filteredCars过滤操作的执行将被推迟,因此如果它的消费者只想要前10个元素,即使用filteredCars.Take(10),那么这不需要构建整个列表(或任何列表)。

答案 2 :(得分:1)

为了做你想做的事,我会使用Linq ToLookup方法创建一个ILookup而不是使用字典。 ToLookup特别适用于此类场景。它基本上是对组进行索引查找。您想按Code对车辆进行分组。

var carCodeLookup = cars.ToLookup(car => car.Code);

carCodeLookup的创建速度很慢,但您可以根据Code使用它来快速查找汽车。要获取公共代码列表中的汽车列表,您可以快速查找。

var filteredCarsQuery = commonCodes.SelectMany(code => carCodeLookup[code]);

这假设您的汽车列表不会经常更改,并且您的commonCodes在查询之间是动态的。

答案 3 :(得分:0)

你可以使用linq join命令,比如

var filteredListOfCars = cars.Join(commonCodes, c => c.Code, cC => cC, (car, code) => car).ToArray();

答案 4 :(得分:0)

这是linq选项的替代方案(也是好主意):如果你想快速进行过滤,我会建议利用内置类型。你可以创建一个DataTable,它有两个字段,数组中汽车的id和代码(如果它们也重要,你可以添加其他10个字段)。然后你可以在它周围创建一个DataView并使用它的filter属性。它在内部使用了一些非常快速的索引(我相信B树),所以你可能无法手动击败它的性能,除非你是一个算法高手,如果你是,你不会在这里问。这取决于你正在做什么以及性能如何重要。

答案 5 :(得分:0)

看起来你真正在检查的是“代码”是否常见,而不是汽车。您可以考虑飞行重量模式,其中汽车共享代码对象的常见实例。然后,代码对象可以具有IsCommon属性和Value属性。 然后,只要commoncodes列表发生更改,您就可以执行更新已使用的Code对象的操作。 现在,当您进行过滤时,您只需要检查每个汽车代码的IsCommon属性