C# 递归执行列表中的funcs

C# 递归执行列表中的funcs,c#,linq,recursion,functional-programming,C#,Linq,Recursion,Functional Programming,给定一个Func列表,是否可以编写一条语句,在列表中迭代并返回如下结果: string result = f1(f2(f..(input)); 我有以下代码(可以运行),但我对临时变量不满意 public static string WrapEachElementWith<T> ( this IEnumerable<T> target, params Func<string, string>[] func ) { str

给定一个
Func
列表,是否可以编写一条语句,在列表中迭代并返回如下结果:

string result = f1(f2(f..(input));
我有以下代码(可以运行),但我对临时变量不满意

public static string WrapEachElementWith<T>
    (   this IEnumerable<T> target, 
        params Func<string, string>[] func )
{
    string result = string.Empty;
    target.Each(s =>
                    {
                        var tmp = s.ToString();
                        func.Reverse().Each(x => tmp = x(tmp));
                        result += tmp;
                    });
    return result;
}
公共静态字符串wrappeachelementwith
(这是一个不可估量的目标,
参数Func[]Func)
{
字符串结果=string.Empty;
目标。每个(s=>
{
var tmp=s.ToString();
func.Reverse().Each(x=>tmp=x(tmp));
结果+=tmp;
});
返回结果;
}
如何简化/重构

更新: 我应该提供更多的背景资料。在Oredev看到高阶JavaScript会话和John滥用c#会话后,我正在玩c#函数编程

目的是生成html

var TABLE = WrapWith("TABLE");
var TR = WrapWith("TR");
var TD = WrapWith("TD");
const string expected = "<TABLE><TR><TD>1</TD></TR><TR><TD>2</TD></TR></TABLE>";

var result = TABLE(stringArray.WrapEachWith(TR, TD));
result.ShouldEqual(expected);

static Func<String, String> WrapWith(string element)
{
    var startTag = '<' + element + '>';
    var endTag = "</" + element + '>';
    return s => startTag + s + endTag;
}
var表=幽灵(“表”);
var TR=幽灵(“TR”);
var TD=幽灵(“TD”);
应为常量字符串=“12”;
var结果=表(stringArray.wrapechwith(TR,TD));
结果:应为合格(预期);
静态Func WrapWith(字符串元素)
{
var startTag='';
var endTag=”
正如@Jon已经提到的,总结这种方式是非常低效的,因此您可能会这样说:

string.Join("", target.Select(
                  item => WrapEachElementWith(item.ToString(), func)));
使用LINQ编写了一个完整的光线跟踪器。我没有仔细看过他的代码,但他描述了使用一种称为“Y组合器”的技术在LINQ语句中创建递归。他引用了,其中给出了这些递归lambda表达式的详细描述


我不知道这是否正是你想要的,但这可能会让你走上正轨。

在我看来,你在做四件事:

  • 将每个项目转换为字符串
  • 依次应用函数
  • 将该复合函数应用于序列中的每个字符串
  • 将结果合并在一起(效率低下)
我将把这四个方面分开——特别是,
string.Join
对于第四部分足够有效,而
Enumerable.Select
则可以执行第三部分

我也会避免颠倒操作的顺序——我希望我指定的第一个操作是第一个应用的操作,就我个人而言

因此,我将重写此方法以返回一个
Func
,然后可与
Select
Join
一起使用。例如:

public static Func<string, string> Compose(params Func<string, string> funcs)
{
    return input => {
        string current = input;
        foreach (var func in funcs)
        {
            current = func(current);
        }
        return current;
    };
}
public static Func Compose(参数Func Func)
{
返回输入=>{
串电流=输入;
foreach(funcs中的var func)
{
电流=func(电流);
}
回流;
};
}
当然,您可以通过以下签名使其成为通用:

public static Func<T, T> Compose(params Func<T, T> funcs)
public static Func Compose(参数Func Func)
然后,您可以这样称呼它:

public static string F<T>
    (   this IEnumerable<T> target, 
        params Func<string, string>[] func )
{
    target.Select(item => WrapEachElementWith(item.ToString(), func))
          .Aggregate((sum, cur) => sum + cur);
}
var composite = Compose<string>(FirstFunction, SecondFunction, ThirdFunction);

var query = string.Join("", items.Select(x => x.ToString())
                                 .Select(composite));
var composite=Compose(第一个函数、第二个函数、第三个函数);
var query=string.Join(“,items.Select(x=>x.ToString())
.选择(复合);

Recursion?类似于
applymanys[]=s
applymanys(f:fs)=applyMany(fs)fs
在C#中?出于好奇,您使用递归的原因是什么?请参阅我问题中的更新,我试图使用我想用的元素列表在HTML中包装元素。我在问题更新中犯了一个错误,它现在有有效的代码。您不会以这种方式生成HTML。就像您不会手工解析XML一样,更不用说了使用正则表达式。这个问题太复杂了,已经解决了,您无法手动处理。每个输入都是T,ToString从一开始就被调用一次。@Jon:我假设它是为每个
目标
的项调用一次。
var composite = Compose<string>(FirstFunction, SecondFunction, ThirdFunction);

var query = string.Join("", items.Select(x => x.ToString())
                                 .Select(composite));