2016-04-08 22 views
2

Ich versuche, funktionale Programmierung Grundlagen zu lernen, Wie kann ich das gleiche Ergebnis mit C# erreichen, weiß ich, linq bietet die Select-Methode für diese Art von Zwecken, aber ich muss dies tun, indem ich selbst zu verstehen, wie man Rekursion über Listen macht. (Ich nehme an, dass Groovy den + Operator für Listen neu definiert).Iterieren über eine Liste rekursiv in C#

/* Probe in Groovy */

def <TResult> List<TResult> Filter(List<TResult> list, Closure cls) 
{ 
    if(list.isEmpty()) { 
     return [] 
    } else { 
     return (cls(list.head()) ? [list.head()] : []) + Filter(list.tail(),cls) 
    } 
} 

(Filter([1,2,3,4,5,6,7,8], { x-> x % 2 == 0 })) 
.each({teger -> println(teger) }) 
+0

Ich bin nicht vertraut mit groovy aber gut in C# trainiert. Könnten Sie kurz erklären, was Sie tun wollen? – Toxantron

+0

Macht nichts, habe es – Toxantron

+1

Wenn Sie wirklich wollen, funktionale Programmierung auf. NET zu lernen, sollten Sie besser F # verwenden. C# ist eine multiple Paradigmensprache und hat eine sehr große Vielfalt an Programmiermöglichkeiten. – Sofver

Antwort

2

Dies überhaupt keinen Sinn macht, ist aber im Grunde C# Version des Codes neu programmiert. Wie ich schon sagte, ist das keine echte Rekursion in C#, aber vielleicht hilft es Ihnen, die Sprache zu verstehen.

public static List<TResult> Filter<TResult>(List<TResult> input, Predicate<TResult> closure) 
{ 
    if (input == null || input.Count == 0) 
     return new List<TResult>(); 
    else 
     return (closure(input.First()) ? new List<TResult> {input.First()} : new List<TResult>()) 
      // Replace '+' 
      .Union(Filter(input.Skip(1).ToList(), closure)).ToList(); 
} 

Eine C# wie Entwurf wäre die folgende:

public static IEnumerable<TResult> RecursiveFilter<TResult>(IEnumerable<TResult> input, Predicate<TResult> closure) 
{ 
    // Break on end 
    if (input == null || !input.Any()) 
     yield break; 

    // Keep going 
    if (closure(input.First())) 
     yield return current; 

    // Recursive progression 
    foreach (var filtered in RecursiveFilter(input.Skip(1), closure)) 
    { 
     yield return filtered; 
    } 
} 

Ausbeute ist Syntaktik Zucker, die das Iterator Muster im Hintergrund erzeugt. Einfach gesagt heißt es jedes Mal, wenn jemand enumerator.MoveNext() auf dem Enumerable aufruft. Weitere Informationen finden Sie unter the MSDN reference. In diesem Beispiel wird ein mehr funktionaler Ansatz für die Rekursion geschaffen, als einfach immer neue Objekte zu erstellen.

Bearbeiten: Alternative mit der Ausbeute hinzugefügt.

+0

gut gemacht! sieht aus wie super nah ... gut besser als was ich getan hätte. – Seabizkit

+0

Danke, das ist, was ich gesucht habe, auch wenn, wie Sie sagten, es keinen Sinn macht, weil C# nicht volle Unterstützung für Functional-Programmierung hat, sieht die Implementierung komplizierter: p –

+0

Und so viele Listen-Objekte zu erstellen ist bei weitem das Schlimmste, was du tun kannst. Normalerweise würdest du für IEnumerable gehen und für so etwas nachgeben. – Toxantron

1

Linq hat Äquivalente zu Kopf und Schwanz, die Sie mit der Liste <T> verwenden können.

Kopf - First() oder FirstOrDefault()

tail - Skip(1)

Skip (1) hat eine ähnliche Wirkung wie lazy evaluation, dass es einen Iterator zurück später ausgeführt werden, anstatt eine neue Liste erstellen jetzt .

Verwandte Themen