2016-11-08 74 views
0

找到元素比方說,我有以下的C#代碼C#在列表

var my_list = new List<string>(); 
// Filling the list with tons of sentences. 
string sentence = Console.ReadLine(); 

有以下任一方式的有什麼區別?

bool c1 = my_list.Contains(sentence); 
bool c2 = my_list.Any(s => s == sentence); 

我想背後的純算法是不完全一樣的。但是我身邊的實際差異是什麼?一種方法比另一種更快還是更有效率?一個方法有時會返回true,另一個會返回false?我應該考慮選擇一種方法還是其他方法?或者它完全取決於我,兩者都可以在任何情況下工作?

+1

考慮到my_list中沒有填充任何內容,兩者都會在大約相同的時間內返回false。如果你想知道哪一個更快,你可以嘗試調試和測試哪一個返回錯誤更快,雖然在所示的條件下,你很難得到一個有效的結果。 – vipersassassin

+0

@vipersassassin你讀過這行嗎? '//用大量的句子填充列表。' –

+0

[你決定哪個更快](https://ericlippert.com/2012/12/17/performance-rant/) – Jamiec

回答

2

最上面的答案並不完全正確(這是一個大O不總是工作的原因)。在這種情況下,任何情況都會比Contains慢(大約增加一倍)。

每次迭代都會有一個額外的調用,您在列表中的每個項目上指定的委託,包含的內容不必做。額外的電話會大大減慢它的速度。

結果將是一樣的,但速度會有很大的不同。

實施例基準:

Stopwatch watch = new Stopwatch(); 

List<string> stringList = new List<string>(); 

for (int i = 0; i < 10000000; i++) 
{ 
    stringList.Add(i.ToString()); 
} 
int t = 0; 
watch.Start(); 
for (int i = 0; i < 1000000; i++) 
    if (stringList.Any(x => x == "29")) 
     t = i; 

watch.Stop(); 
("Any takes: " + watch.ElapsedMilliseconds).Dump(); 
GC.Collect(); 
watch.Restart(); 

for (int i = 0; i < 1000000; i++) 
    if (stringList.Contains("29")) 
     t = i; 

watch.Stop(); 

("Contains takes: " + watch.ElapsedMilliseconds).Dump(); 

結果:

Any takes: 481 
Contains takes: 235 

大小和數量的迭代將不影響%的差異的,任何將總是慢得多。

2

實際上,兩者的操作方式幾乎相同:迭代列表項並檢查句子是否與任何列表元素相匹配,複雜度大約爲O(n)。我會認爲List.Contains,因爲這是一個更容易,更自然,但它是完全優惠!

現在,如果您在尋找複雜度和速度方面更快,我建議您使用HashSet<T>。一般來說,散列函數的查找大約有O(1),因爲哈希函數在理論上應該是一個常量時間操作。再次,只是一個建議:)

+1

好吧,這幾乎只有一個人的喜好。這就是我想知道的,謝謝。 :) – Kishlin

1

對於string對象,沒有什麼區別,因爲== operator只是簡單地調用String.Equals==.Equals之間

但是,對於其他的對象,可能有分歧 - 看implementation of .Contains,它將使用EqualityComparer<T>.Default,這隻要掛鉤到Equals(T)你的類實現IEquatable<T>(其中T本身)。在沒有超載==的情況下,大多數類替代使用參考比較==,因爲這是他們從Object繼承的內容。