2010-03-17 132 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屬性