LINQ-Abfrage, die Elemente aus einer Objektliste filtert

107115
WizLiz

Ich habe zwei Objektlisten Personund PersonResult. Beide sind über die Immobilie miteinander verbunden PersonId. Ich muss einen Filter für die Liste erstellen PersonResult, der bestimmte Kriterien für Person(z Person.Gender == "female". B. ) erfüllt .

Ich verwende derzeit die folgende LINQ-Abfrage, um dies zu erreichen:

PersonResultList = PersonResultList.Where(pr => 
    PersonList.FirstOrDefault(p => pr.PersonId == p.PersonId) != null && 
    PersonList.FirstOrDefault(p => pr.PersonId == p.PersonId).Gender == "female");

Dies funktioniert anscheinend gut, jedoch muss ich zweimal durch PersonList durchlaufen, um zu prüfen, ob die Person existiert und ihr Geschlecht. Gibt es einen eleganteren Weg, um dies zu erreichen?

Antworten
11

2 Antworten auf die Frage

12
jnm2

Was Sie tun, filtert PersonResultListnur weibliche Geschlechter. Durch das Hinzufügen von Informationen aus Informationen PersonListwird dies klarer und effizienter ausgedrückt.

Erweiterungsmethoden verwenden:

PersonResultList = PersonResultList.Join(
    PersonList.Where(_ => _.Gender == "female"), 
    personResult => personResult.PersonId,
    person => person.PersonId, 
    (personResult, person) => personResult);

Ziemlich dasselbe, aber klarer:

PersonResultList = from personResult in PersonResultList
                   join person in PersonList on personResult.PersonId equals person.PersonId
                   where person.Gender == "female"
                   select personResult;
Ich bevorzuge die Erweiterungsmethode für LINQ, daher habe ich nicht an diesen Ansatz gedacht. Ich werde mir das beim nächsten Mal merken, wenn ich LINQ-Abfragen schreibe. WizLiz vor 5 Jahren 0
Mein erster Codeblock ist eigentlich der Ansatz der Erweiterungsmethode, den Sie bevorzugen. Dies ist effizienter als die Antwort von Heslacher (die manuell über verschachtelte Schleifen verbunden wird) und spricht die Absicht des Codes klarer an als die manuelle Implementierung geschachtelter Schleifen. Jeder Block hier ist viel besser LINQ. jnm2 vor 5 Jahren 0
++ Manchmal ist die Abfragesyntax viel verständlicher. RubberDuck vor 5 Jahren 5
@RubberDuck Ich stimme dir in bestimmten Fällen zu. Wenn Sie jedoch eine Reihe von Vorgängen ausführen müssen (z. B. Gruppieren, Sortieren, Überspringen, Auswählen, Verknüpfen, Auswählen), wird es schnell überladen, zumindest IMO Basic vor 5 Jahren 0
Zustimmt @Basic. Ich habe doch * manchmal * gesagt. =;) - RubberDuck vor 5 Jahren 0
9
Heslacher

Sie können einfach die Bedingungen in der FirstOrDefault()Art kombinieren

PersonResultList = PersonResultList
    .Where(pr => PersonList
                    .FirstOrDefault(p => pr.PersonId == p.PersonId 
                                         && p.Gender == "female") != null );  

Da ich nur Ihren bestehenden Code geändert habe, fiel mir nicht ein, was Nikita Brizhak hier kommentierte .

Sie sollten wahrscheinlich Any anstelle von FirstOrDefault verwenden

Lassen Sie uns den Code also ändern

PersonResultList = PersonResultList
        .Where(pr => PersonList
                        .Any(p => pr.PersonId == p.PersonId 
                              && p.Gender == "female")); 

Dies basiert auf der Annahme, dass für jeden Eintrag in der ersten Liste nur ein Eintrag in der zweiten Liste vorhanden ist.

Sie sollten wahrscheinlich `Any` anstelle von` FirstOrDefault` verwenden :) Nikita B vor 5 Jahren 5
Ersetzt `Any ()` die Anforderungen für die Überprüfung von `! = Null` Ich bin mit linq-Abfragen noch nicht so vertraut. WizLiz vor 5 Jahren 0
`Any ()` prüft, ob ein Element die Bedingung erfüllt. Wenn kein Artikel vorhanden ist, wird dieses "pr" nicht in das Ergebnis aufgenommen. Heslacher vor 5 Jahren 0
Danke, diese Art von Dingen hilft mir viel, bessere LINQ zu schreiben. WizLiz vor 5 Jahren 0
Ist "Any" schneller als "FirstOrDefault"? John Odom vor 5 Jahren 0
Bei LINQ geht es nicht wirklich um Geschwindigkeit, sondern um einfache Codierung und Wartbarkeit. Wenn eine Abfrage geschwindigkeitskritisch ist, müssen Sie sie möglicherweise manuell optimieren. Snowbody vor 5 Jahren 1
Any () funktioniert ähnlich wie FirstOrDefault (), aber anstatt das erste Element zurückzugeben, wird true zurückgegeben, und es wird nicht null zurückgegeben, sondern false. Ich würde erwarten, dass ihre Leistung für In-Memory-Vorgänge praktisch identisch ist. In Szenarien, in denen die Abfrage in SQL übersetzt oder anderweitig nicht im Arbeitsspeicher von .NET-Objekten ausgeführt wird, kann ein größerer Unterschied bestehen. Die Unterschiede sind jedoch sehr situativ. Taudris vor 5 Jahren 1