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