LINQ-Rekursion-Funktion?
Nehmen wir als diese n-tier-tief-Struktur, zum Beispiel:
public class SomeItem
{
public Guid ID { get;set; }
public string Name { get; set; }
public bool HasChildren { get;set; }
public IEnumerable<SomeItem> Children { get; set; }
}
Wenn ich bin auf der Suche, um ein bestimmtes Element durch ID (irgendwo in der Struktur) gibt es einige LINQ-Güte, die ich verwenden können, um es leicht zu bekommen in eine einzelne Anweisung oder muss ich nutzen, um einige rekursive Funktion, wie unten:
private SomeItem GetSomeItem(IEnumerable<SomeItem> items, Guid ID)
{
foreach (var item in items)
{
if (item.ID == ID)
{
return item;
}
else if (item.HasChildren)
{
return GetSomeItem(item.Children, ID);
}
}
return null;
}
Brauchen Sie wirklich die HasChildren-Eigenschaft?
Nicht wirklich, nur ein Helfer, so dass es liest sich besser 🙂 - Kinder.Count > 0
Kinder.Jede() 🙂
Nicht wirklich, nur ein Helfer, so dass es liest sich besser 🙂 - Kinder.Count > 0
Kinder.Jede() 🙂
InformationsquelleAutor The_Butcher | 2011-01-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
LINQ nicht wirklich "tun" Rekursion schön. Ihre Lösung scheint angemessen zu sein - obwohl ich nicht sicher bin HasChildren wirklich erforderlich ist... warum nicht einfach eine leere Liste nach einem Element mit keine Kinder?
Alternative ist das schreiben einer
DescendantsAndSelf
Methode, die zurückkehren wird alle der Nachkommen (einschließlich der Element selbst), so etwas wie dieses;Jedoch, wenn der Baum ist tief, die endet als sehr ineffizient, da jedes Element muss "passieren" alle Iteratoren von seiner Abstammung. Wes Dyer hat gebloggt über diese, zeigt eine effizientere Implementierung.
Sowieso, wenn Sie eine Methode wie diese (aber es ist implementiert), können Sie einfach eine normale "where" - Klausel, um ein Element (oder die Erste/FirstOrDefault etc).
Wenn Sie wiederholt aufrufen DescendantsAndSelf() wird es Durchlaufen, den ganzen Baum wieder oder muss LINQ halten Sie das Ergebnis?
LINQ macht nichts Magisches hier. Es geht nicht um cache etwas für Sie. Natürlich, man könnte ToList zum erzeugen einer Cache-Kopie selbst.
Stimmt, die Anzahl der Iteratoren erzeugt wird, basierend auf der Anzahl der Knoten - aber die Anzahl der Iteratoren jedes Element muss passieren, während es propagiert, um die top-iterator hängt von der Tiefe des Baumes. So einen tiefen Baum wird immer noch weniger effizient zu Durchlaufen, als ein oberflächlicher. Bearbeiten, um das klarer.
Ich wollte gerade eine neue Frage stellen über rekursive linq und die Antwort(die
DescendantsAndSelf
trick) ist groß.(kombiniert mit SelectMany). danke. Kann dies geschrieben werden als Extension-Methode ?InformationsquelleAutor Jon Skeet
hoffe, das hilft
Dies ist nicht rekursiv, aber.... nur eine Ebene tief 🙁
InformationsquelleAutor Bonshington
Hier ist einer, der ohne Rekursion. Dies vermeidet die Kosten, die durch mehrere Schichten von Iteratoren, also ich denke, es ist ungefähr so effizient, wie Sie kommen.
Aufrufen, etwa so:
var c = q[0]; q.RemoveAt(0);
ist wirklich eine potenziell ineffiziente Umsetzung derQueue.Dequeue()
Methodedu hast Recht.
InformationsquelleAutor DenNukem
Ist es wichtig, denken Sie daran, Sie müssen nicht alles tun, was mit LINQ, oder Standard-Rekursion. Es gibt interessante Optionen, wenn Sie Daten-Strukturen. Das folgende ist eine einfache Abflachung Funktion falls es jemanden interessiert.
InformationsquelleAutor Felipe Ramos
Zwar gibt es Verlängerung Methoden, mit denen die Rekursion in LINQ (und wahrscheinlich Aussehen wie Ihre Funktion) keine sind, zur Verfügung gestellt aus dem Kasten heraus.
Beispiele für diese Erweiterung Methoden finden hier oder hier.
Ich würde sagen, Ihre Funktion ist in Ordnung.
InformationsquelleAutor Jens