它有一个属性: 字符串代码 和另外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的记录
如何降低执行时间??
答案 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属性