对结果重复应用函数

本文关键字:应用 函数 结果 | 更新日期: 2023-09-27 18:08:13

.NET或LINQ是否提供任何标准方法来将函数重复应用于自身,直到结果满足终止条件并返回所有结果的IEnumerable ?

例如,假设你有一个树,想要找到从节点到根的路径:那么函数是"获取节点n的父节点",终止准则是"节点是根"。

这里是一个整数值的小例子,其中函数是"返回一半值",终止条件是"值为0":

static void Main(string[] args)
{
    int val = 4321;
    List<int> pathToRoot = new List<int>{val};
    for (;;)
    {
        val = GetParent(val);
        if (val == 0)
        {
            break;
        }
        pathToRoot.Add(val);
    }
    // Prints: 4321,2160,1080,540,270,135,67,33,16,8,4,2,1
    Console.WriteLine(string.Join(",", pathToRoot));
}
private static int GetParent(int child)
{
    return child / 2;
}

我想用标准的。net或LINQ方法替换for循环。如果我必须自己写这个函数,它应该是这样的:

public static class Generator
{
    public static IEnumerable<T> ApplyRepeatedly<T>(T seed,
        Func<T, T> func, Func<T, bool> predicate)
    {
        yield return seed;
        for (;;)
        {
            seed = func(seed);
            if (predicate(seed))
            {
                yield break;
            }
            yield return seed;
        }
    }

你可以这样使用:

IEnumerable<int> pathToRoot = Generator.ApplyRepeatedly(
    4321, GetParent, i => i == 0);

因为我不想重新发明轮子,我的问题是:是否。net或LINQ已经提供了类似ApplyRepeatedly<T>()的东西?

对结果重复应用函数

系统中没有任何内容。Linq,但f#有seq.unfold,所以你可以使用:

var uf = FSharpFunc<int, FSharpOption<Tuple<int, int>>>.FromConverter(i =>
        {
            if (i == 0) return FSharpOption<Tuple<int, int>>.None;
            else return FSharpOption<Tuple<int, int>>.Some(Tuple.Create(i, i / 2));
        });
IEnumerable<int> pathToRoot = SeqModule.Unfold(uf, 4321);