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