2016-02-12 46 views
3

我有一個對象的集合,我想檢索所有具有其中一個屬性匹配搜索字符串的對象。到目前爲止,我已經嘗試了幾種過濾方法,即List.ForAll,IEnumerable.Where和ParallelQuery.Where。最快的方法來過濾集合C#

List<Foo> cache = GetAllObjs(); // source list containing lots of objects 

選項1:

List<Foo> foos = cache.AsParallel().Where(x => x.Name == "bar").ToList(); 

選項2:

List<Foo> foos = cache.Where(x => x.Name == "bar").ToList(); 

選項3:

List<Foo> foos = cache.FindAll(x => x.Name == "bar"); 

由於ParallelQuery.Where利用多個內核,它似乎是最快的方案。除此之外,是否還有其他方法進行過濾,例如使用不同的集合類型或過濾功能?源集合不一定是List。

+4

[比賽馬](http://ericlippert.com/2012/12/17/performance-rant/)...它可能取決於陣列的大小和其他因素 – Sayse

+0

我沒有比賽的馬匹。 ..我反正可以想到的三個。我想知道是否有不同的馬匹,我可以比賽... – painiyff

+0

很難說最好的選擇(給定的)是,就像我說的,對於較小的陣列/列表,旋轉時間並行線程在執行時間方面可能不會帶來任何好處。對'ToList'的調用可能不是必需的,或者 – Sayse

回答

8

除此之外,還有其他的過濾方法,例如使用不同的集合類型或過濾函數嗎?

如果可以有多個具有相同名稱的對象,則可以使用Lookup<string, Foo>。你可以把查詢作爲string -> List<Foo>詞典:

// create 
var foosByName = GetAllObjs().ToLookup(x => x.Name, x => x); 

// search 
var barFoos = foosByName["bar"].ToList(); 

當然,如果只有一個Foo每一個名字,一個經典的Dictionary<string, Foo>將服務。

在字典或查找中搜索(通常)是O(1)操作,而您的問題中的搜索方法是O(n)。

+2

哦,我改成了'Lookup ',它使得搜索幾乎是瞬時的。因爲我必須進行子字符串匹配,就像在'x.Name.Contains(「bar」)'中一樣,我必須創建一個帶有索引的'Lookup'作爲'Name'的所有可能的子字符串。它在preprosessing階段吃了很多內存,但搜索本身閃電般快。 – painiyff

+1

@painiyff:很高興聽到這一點。如果您需要低內存消耗*和*前綴搜索支持,可以[使用trie(原文如此)或通過SortedDictionary進行二進制搜索](http://stackoverflow.com/q/1902108/87698)。 – Heinzi