2013-02-15 7 views
5

Hallo kann sagen, ich habe Baum vom Typ folgendenChecking Länge des Baumes Linq mit

public class Element 
{ 
    public List<Element> element; 
} 

kann sagen Wurzel des Baumes ist

Element root = GetTree(); 

Ich weiß es möglich ist, Länge dieses Baumes zu überprüfen mit Rekursion aber ist es möglich, die Länge dieses Baumes mit Linq zu überprüfen?

+0

Ich würde die rekursive Methode verwenden, um die Anzahl der Elemente in der Struktur zu zählen. Aber es wäre schön, andere Ideen zu hören. Gute Frage. – Maris

+0

Was meinst du mit der Länge des Baumes? Die maximale Tiefe? Die Gesamtzahl der Artikel? – Rawling

+0

Die maximale Tiefe – kosnkov

Antwort

2

Sie könnten eine Erweiterungsmethode schreiben, um alle Elemente rekursiv abzurufen.

var allElements = root.element.Traverse(el => el.element); 

Zum Beispiel:

public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse) 
{ 
    foreach (T item in source) 
    { 
     yield return item; 

     IEnumerable<T> seqRecurse = fnRecurse(item); 
     if (seqRecurse != null) 
     { 
      foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse)) 
      { 
       yield return itemRecurse; 
      } 
     } 
    } 
} 
1

eine neue Erweiterung Methode hinzufügen;

public static int CountX(this Element e) 
    { 
     int temp = 0; 
     if (e.element != null) 
     { 
      temp = e.element.Count; 
      e.element.ForEach(q => temp += q.CountX()); 
     } 
     return temp; 
    } 

und nennen Sie es wie;

int depthCount= a.CountX(); 
1

Soweit ich weiß, kann man recusive Linq nicht haben, weil rekursive lambdas mit aus der Box nicht möglich ist.

Die originellste Antwort, die ich geben kann, basiert auf einem rekursiven Lambda-Ausdruck, der auf einem wiederverwendbaren Fixpunktoperator basiert. Sie werden die meisten Linq-Mechanismen finden. Aber ich fürchte, der Fixpoint-Teil ist der Grund, warum es keine reine Linq-Antwort gibt.

public static class FixPoint 
{ 
    // Reusable fixpoint operator 
    public static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f) 
    { 
     return t => f(Fix<T, TResult>(f))(t); 
    } 
} 

public class Element 
{ 
    public List<Element> element; 


    public int CalculateMaxDepth() 
    { 
     return FixPoint.Fix<List<Element>, int>(
      // recursive lambda 
      f => 
      listElement => listElement == null || listElement.Count == 0 
       ? 0 
       : 1 + listElement.Select(e => f(e.element)).Max()) 
      (this.element); 
    } 

    [Test] 
    public void myTest() 
    { 
     var elt = new Element() { element = new List<Element> { new Element() { element = new List<Element> { new Element() { element = new List<Element> { new Element() } } } } } }; 
     Assert.AreEqual(3, elt.CalculateMaxDepth()); 
    } 
}