Frage

Ich suche nach einer sehr schnellen Möglichkeit, eine Sammlung in C# herunterzufiltern.Ich verwende derzeit generische List<object>-Sammlungen, bin aber offen für die Verwendung anderer Strukturen, wenn diese eine bessere Leistung erbringen.

Derzeit erstelle ich gerade ein neues List<object> und durchlaufe die ursprüngliche Liste.Wenn die Filterkriterien übereinstimmen, füge ich eine Kopie in die neue Liste ein.

Gibt es einen besseren Weg, dies zu tun?Gibt es eine Möglichkeit, vor Ort zu filtern, sodass keine temporäre Liste erforderlich ist?

War es hilfreich?

Lösung

Wenn Sie C# 3.0 verwenden, können Sie Linq viel besser und eleganter verwenden:

List<int> myList = GetListOfIntsFromSomewhere();

// This will filter out the list of ints that are > than 7, Where returns an
// IEnumerable<T> so a call to ToList is required to convert back to a List<T>.
List<int> filteredList = myList.Where( x => x > 7).ToList();

Wenn Sie das nicht finden können .Where, das bedeutet, dass Sie importieren müssen using System.Linq; oben in Ihrer Datei.

Andere Tipps

Hier ist ein Codeblock/Beispiel für eine Listenfilterung mit drei verschiedenen Methoden, die ich zusammengestellt habe, um Lambdas- und LINQ-basierte Listenfilterung zu zeigen.

#region List Filtering

static void Main(string[] args)
{
    ListFiltering();
    Console.ReadLine();
}

private static void ListFiltering()
{
    var PersonList = new List<Person>();

    PersonList.Add(new Person() { Age = 23, Name = "Jon", Gender = "M" }); //Non-Constructor Object Property Initialization
    PersonList.Add(new Person() { Age = 24, Name = "Jack", Gender = "M" });
    PersonList.Add(new Person() { Age = 29, Name = "Billy", Gender = "M" });

    PersonList.Add(new Person() { Age = 33, Name = "Bob", Gender = "M" });
    PersonList.Add(new Person() { Age = 45, Name = "Frank", Gender = "M" });

    PersonList.Add(new Person() { Age = 24, Name = "Anna", Gender = "F" });
    PersonList.Add(new Person() { Age = 29, Name = "Sue", Gender = "F" });
    PersonList.Add(new Person() { Age = 35, Name = "Sally", Gender = "F" });
    PersonList.Add(new Person() { Age = 36, Name = "Jane", Gender = "F" });
    PersonList.Add(new Person() { Age = 42, Name = "Jill", Gender = "F" });

    //Logic: Show me all males that are less than 30 years old.

    Console.WriteLine("");
    //Iterative Method
    Console.WriteLine("List Filter Normal Way:");
    foreach (var p in PersonList)
        if (p.Gender == "M" && p.Age < 30)
            Console.WriteLine(p.Name + " is " + p.Age);

    Console.WriteLine("");
    //Lambda Filter Method
    Console.WriteLine("List Filter Lambda Way");
    foreach (var p in PersonList.Where(p => (p.Gender == "M" && p.Age < 30))) //.Where is an extension method
        Console.WriteLine(p.Name + " is " + p.Age);

    Console.WriteLine("");
    //LINQ Query Method
    Console.WriteLine("List Filter LINQ Way:");
    foreach (var v in from p in PersonList
                      where p.Gender == "M" && p.Age < 30
                      select new { p.Name, p.Age })
        Console.WriteLine(v.Name + " is " + v.Age);
}

private class Person
{
    public Person() { }
    public int Age { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
}

#endregion

List verfügt über die FindAll-Methode, die die Filterung für Sie durchführt und eine Teilmenge der Liste zurückgibt.

Der msdn hat hier ein tolles Codebeispiel: http://msdn.microsoft.com/en-us/library/aa701359(VS.80).aspx

BEARBEITEN:Ich habe dies geschrieben, bevor ich ein gutes Verständnis von Linq und der Where()-Methode hatte.Wenn ich das heute schreiben würde, würde ich wahrscheinlich die oben von Jorge erwähnte Methode verwenden.Die FindAll-Methode funktioniert jedoch weiterhin, wenn Sie in einer .NET 2.0-Umgebung stecken bleiben.

Sie können IEnumerable verwenden, um die Notwendigkeit einer temporären Liste zu beseitigen.

public IEnumerable<T> GetFilteredItems(IEnumerable<T> collection)
{
    foreach (T item in collection)
    if (Matches<T>(item))
    {
        yield return item;
    }
}

Dabei ist „Matches“ der Name Ihrer Filtermethode.Und Sie können dies wie folgt verwenden:

IEnumerable<MyType> filteredItems = GetFilteredItems(myList);
foreach (MyType item in filteredItems)
{
    // do sth with your filtered items
}

Dadurch wird bei Bedarf die Funktion „GetFilteredItems“ aufgerufen. In einigen Fällen, in denen Sie nicht alle Elemente in der gefilterten Sammlung verwenden, kann dies zu einer guten Leistungssteigerung führen.

Du kannst den ... benutzen Finde alle Methode der Liste, die einen Delegaten zum Filtern bereitstellt.Allerdings stimme ich @ zuIainMH dass es sich nicht lohnt, sich zu viele Sorgen zu machen, es sei denn, es handelt sich um eine riesige Liste.

Um dies vor Ort zu tun, können Sie die RemoveAll-Methode der „List<>“-Klasse zusammen mit einer benutzerdefinierten „Predicate“-Klasse verwenden … aber alles, was Sie tun müssen, ist, den Code zu bereinigen …Unter der Haube macht es dasselbe wie Sie ... aber ja, es macht es an Ort und Stelle, also machen Sie dasselbe mit der temporären Liste.

Die Verwendung von Linq ist relativ langsamer als die Verwendung eines Prädikats, das der Lists-FindAll-Methode bereitgestellt wird.Seien Sie auch bei Linq vorsichtig, da die Aufzählung der Liste erst dann tatsächlich ausgeführt wird, wenn Sie auf das Ergebnis zugreifen.Dies kann dazu führen, dass, wenn Sie glauben, eine gefilterte Liste erstellt zu haben, der Inhalt möglicherweise von dem abweicht, was Sie erwartet haben, als Sie sie tatsächlich gelesen haben.

Wenn Sie C# 3.0 verwenden, können Sie linq verwenden

Wenn Sie möchten, können Sie auch die spezielle Abfragesyntax verwenden, die vom C#-3-Compiler bereitgestellt wird:

var filteredList = from x in myList
                   where x > 7
                   select x;

Wenn Ihre Liste sehr umfangreich ist und Sie wiederholt filtern, können Sie die ursprüngliche Liste nach dem Filterattribut sortieren und eine binäre Suche durchführen, um die Start- und Endpunkte zu finden.

Anfangszeit O(n*log(n)), dann O(log(n)).

Die Standardfilterung benötigt jedes Mal O(n).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top