Szukam bardzo szybkiego sposobu na odfiltrowanie kolekcji w C #. Obecnie używam ogólnych kolekcji List <object>, ale jestem otwarty na używanie innych struktur, jeśli działają lepiej.
Obecnie właśnie tworzę nowy List <object> i przeglądam oryginalną listę. Jeśli kryteria filtrowania są zgodne, umieszczam kopię na nowej liście.
Czy jest lepszy sposób na zrobienie tego? Czy istnieje sposób na filtrowanie, aby nie było potrzeby tworzenia tymczasowej listy?
c#
collections
filtering
Jason Z
źródło
źródło
Odpowiedzi:
Jeśli używasz C # 3.0, możesz użyć linq, o wiele lepiej i bardziej elegancko:
Jeśli nie możesz znaleźć
.Where
, oznacza to, że musisz importowaćusing System.Linq;
na początku pliku.źródło
.Where(predefinedQuery)
zamiast używać.Where(x => x > 7)
?public bool predefinedQuery(int x) { return x > 7; }
. : . Wtedy.Where(predefinedQuery)
będzie działać dobrze.Oto blok kodu / przykład filtrowania list przy użyciu trzech różnych metod, które połączyłem, aby pokazać filtrowanie list oparte na Lambdzie i LINQ.
źródło
List<T>
maFindAll
metodę, która wykona filtrowanie za Ciebie i zwróci podzbiór listy.MSDN ma tutaj świetny przykład kodu: http://msdn.microsoft.com/en-us/library/aa701359(VS.80).aspx
EDYCJA: napisałem to, zanim dobrze zrozumiałem LINQ i
Where()
metodę. Gdybym miał dziś to napisać, prawdopodobnie użyłbym metody, o której wspomniał Jorge powyżej. TaFindAll
metoda nadal działa, jeśli utkniesz w środowisku .NET 2.0.źródło
Możesz użyć IEnumerable, aby wyeliminować potrzebę listy tymczasowej.
gdzie Dopasowania to nazwa metody filtrującej. Możesz użyć tego na przykład:
Spowoduje to wywołanie funkcji GetFilteredItems w razie potrzeby, aw niektórych przypadkach, gdy nie używasz wszystkich elementów w filtrowanej kolekcji, może to zapewnić dobry wzrost wydajności.
źródło
Aby to zrobić na miejscu, możesz użyć metody RemoveAll klasy „List <>” wraz z niestandardową klasą „Predicate” ... ale wszystko, co robi, to wyczyszczenie kodu ... pod maską robi to samo rzecz, którą jesteś ... ale tak, robi to na miejscu, więc robisz to samo na liście tymczasowej.
źródło
Możesz użyć metody FindAll listy, zapewniając delegata do filtrowania. Chociaż zgadzam się z @ IainMH , że nie warto się zbytnio martwić, chyba że jest to ogromna lista.
źródło
Lub, jeśli wolisz, użyj specjalnej składni zapytania dostarczonej przez kompilator C # 3:
źródło
Korzystanie z LINQ jest stosunkowo wolniejsze niż użycie predykatu dostarczonego do
FindAll
metody Lists . Zachowaj również ostrożność w przypadku LINQ, ponieważ wyliczenielist
nie jest faktycznie wykonywane, dopóki nie uzyskasz dostępu do wyniku. Może to oznaczać, że jeśli myślisz, że utworzyłeś przefiltrowaną listę, zawartość może różnić się od tego, czego się spodziewałeś, kiedy faktycznie ją czytasz.źródło
Jeśli twoja lista jest bardzo duża i wielokrotnie filtrujesz - możesz posortować oryginalną listę według atrybutu filtru, wyszukiwanie binarne, aby znaleźć punkty początkowe i końcowe.
Czas początkowy O (n * log (n)), a następnie O (log (n)).
Standardowe filtrowanie za każdym razem zajmie O (n).
źródło