2010-03-17 128 views
6

它有一个属性: 字符串代码 和其他10。如何优化此代码

常见代码是字符串列表(字符串[]) 汽车列表(汽车[]) filteredListOfCars是列表。

for (int index = 0; index < cars.Length; index++) 
{ 
    Car car = cars[index]; 
    if (commonCodes.Contains(car.Code)) 
    { 
     filteredListOfCars.Add(car); 
    } 
} 

不幸的是这片方法太长。

我有大约5万条记录

我如何能降低执行时间?

回答

16

Jared已经正确地指出你可以用HashSet来优化它,但是我也想指出整个方法是不必要的,浪费存储器的输出列表并且使代码更清晰。

你可以写整个方法为:

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

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

+0

Linq Join方法为您查找逻辑,因此您不必指定HashSet。参加(commonCodes,car => car.Code,code => code,(car,code)=> car) – DRBlaise 2010-03-17 19:52:09

+0

@DRBlaise:确实'Join'使用一个哈希表,但它也是一个实现细节,依赖于这些事情是有风险的,因为它们可能会发生变化(即使不太可能发生变化)。如果你想保证一定的性能水平,那么你应该明确语义。 – Aaronaught 2010-03-17 20:28:38

+0

为什么int?新哈希是不正确的? – user278618 2010-03-17 22:54:52

20

最简单的优化转换这一领域的空白,从commonCodes一个string[]以更快的查找结构,如Dictionary<string,object>HashSet<string>,如果你使用的是.NET 3.5或以上。这将减少此循环的大O复杂性,并取决于commonCodes的大小应使此循环执行得更快。

+0

+1打我到30秒; p – Jake 2010-03-17 16:20:44

0

你可以使用LINQ join命令,像

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

这里的LINQ选项的选择(这也是一个好的想法):如果你想快速地做过滤,我会建议利用建成的类型。你可以创建一个DataTable,它有两个字段,数组中的汽车的id和代码(如果它们同样重要,你可以添加其他10个东西)。然后你可以在它周围创建一个DataView并使用它的过滤器属性。它内部使用了一些非常快速的索引(我相信B树),所以你可能无法手动打败它的性能,除非你是算法专家,如果你是的话,你不会在这里问。这取决于你在做什么以及有多少表现很重要。

1

要做你想做的事情,我会使用Linq ToLookup方法来创建一个ILookup,而不是使用字典。 ToLookup特别针对这种情况。它基本上是对组进行索引查找。你想按Code分组你的车。

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

的carCodeLookup的建立将是缓慢的,但那么你可以使用它基于Code汽车的快速查找。要获得您的通用代码列表中的汽车列表,您可以快速查找。

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

这假设你的汽车列表不会经常改变,而且它是你的commonCodes在查询之间是动态的。

0

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