IEnumerable<int> numbers= new List<int> { 1,2,3,11,22,33}; if (numbers.Count() > 0) { //code... }
Nic wielkiego jeżeli mamy listę do tyś. elementów, ale co się stanie, gdy lista składa się z dużo większej liczby elementów lub elementy są jako 'ciężkie obiekty'. Metoda Count() ma liniową złożoność obliczeniową. Poniższa tabela przedstawia ilość elementów i czas działania metody Count w ms. Oczywiście na innym komputerze czas działania metody będzie inny.
Count | Count time |
---|---|
100 | 0 |
1,000 | 0 |
10,000 | 0 |
100,000 | 1 |
1,000,000 | 13 |
10,000,000 | 130 |
100,000,000 | 1332 |
1,000,000,000 | 13243 |
Zastanawiam, się dlaczego programiści nie używają metody Any(), która ma złożoność O(1). Metoda ta sprawdza czy jest przynajmniej jeden element w liście. A co jeżeli będziemy chcieli sprawdzić czy w liście jest przynajmniej n-elementów? Ja wpadłem na parę rozwiązań.
if (numbers.Count() >= indexOf) { //count } if (numbers .Select((x, i) => new { x, i }) .Any(arg => arg.i >= indexOf)) { //select&any } if (numbers .Skip(indexOf) .Any()) { //skip&any } if (numbers .ElementAtOrDefault(indexOf+ 1) != default(int)) { //elementAt } if (numbers .Take(hasIndexes) .Count() == indexOf) { //take&count }
Zmienna indexOf określa ile elementów chcielibyśmy, aby było w liście. Metoda ElementAtOrDefault mogła by spełniać warunek zadania tylko wtedy, gdyby lista nie zawierała domyślnej wartości elementu. Poniżej przedstawiam wyniki czasu działania dla tych sposobów. Czas jest liczony w ms.
IndexOf | Count | Select&Any | Skip&Any | ElementAt | Take&Count |
---|---|---|---|---|---|
1 | 28265 | 2 | 1 | 0 | 1 |
10 | 27769 | 0 | 0 | 0 | 0 |
100 | 27916 | 0 | 0 | 0 | 0 |
1,000 | 28604 | 0 | 0 | 0 | 0 |
10,000 | 28423 | 0 | 0 | 0 | 0 |
100,000 | 28605 | 3 | 1 | 1 | 2 |
1,000,000 | 28541 | 32 | 12 | 14 | 21 |
10,000,000 | 28408 | 321 | 128 | 137 | 205 |
100,000,000 | 28529 | 3222 | 1302 | 1390 | 2065 |
1,000,000,000 | 28583 | 32342 | 13268 | 13789 | 20489 |
Wykres w skali liniowej i logarytmicznej:
Wniosek jest taki, że najlepiej przeskoczyć potrzebną liczbę elementów w liście i sprawdzić czy jest jakiś element (skip&any).
Gdyby lista byłaby IList<T> to można jeszcze zastosować indexOf lub właściwość Count:
if (numbers .IndexOf(hasIndexes) != -1) { }Jeżeli znasz inne sposoby to opisz je w komentarzu. Jestem ciekaw co można jeszcze zrobić.
Brak komentarzy:
Prześlij komentarz