简体   繁体   English

在C#中递归遍历列表

[英]Iterating over a list recursively in C#

I am trying to learn functional programming fundamentals , How can I achieve the same result using C#, I know linq provides the Select Method for this kind of purposes , but I need to do this by myself to understand how to do recursion over lists .( I assume that Groovy redefines the + operator for lists ) . 我正在尝试学习函数式编程的基础知识,我如何使用C#可以达到相同的结果,我知道linq为此目的提供了Select方法,但是我需要自己做这个才能了解如何对列表进行递归。(我假设Groovy为列表重新定义了+运算符)。

/* sample in Groovy */ / * 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) })

This makes no sense at all but is basically reprogrammed C# version of your code. 这一点都没有意义,但基本上是代码的重新编程C#版本。 Like I said this is no real world use of recursion in C# but maybe it helps you understand the language. 就像我说的那样,这不是C#中对递归的实际使用,但也许可以帮助您理解该语言。

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();
}

A more c# like design would be the following: 类似c#的设计如下:

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;
    }
}

Yield is syntactics sugar that creates the iterator pattern in the background. Yield是在后台创建迭代器模式的语法糖。 Simply put is is called everytime someone calls enumerator.MoveNext() on the enumerable. 每当有人在枚举数上调用enumerator.MoveNext() ,都会调用简单地说。 For more information please look at the MSDN reference . 有关更多信息,请参见MSDN参考 So in this examle it create a more functional approach to the recursion than simply creating new objects all the time. 因此,在此示例中,它比始终简单地创建新对象创建了一种更实用的递归方法。

Edit: Added alternative with yield. 编辑:增加了产量的替代方案。

Linq has equivalents to head and tail, which you can use with List<T>. Linq与头和尾具有等效项,您可以将其与List <T>一起使用。

head - First() or FirstOrDefault() 头- 第一个()FirstOrDefault()

tail - Skip(1) 尾巴- 跳过(1)

Skip(1) has a similar effect to lazy evaluation, in that it returns an iterator to be executed later, rather than creating a new list now. Skip(1)与懒惰求值具有相似的效果,因为它返回一个迭代器以待稍后执行,而不是现在创建一个新列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM