简体   繁体   English

转换Func <T, String> 到Func <T, bool>

[英]Convert Func<T, String> to Func<T, bool>

I think my mind is exploding trying to figure out Funcs... If this makes no sense, I apologize, right now it make sense to me but its been a long day already .... 我想我的想法正在爆发,试图找出Funcs ......如果这没有意义,我道歉,现在它对我来说有意义,但它已经过了漫长的一天......

1) Assuming you are given a func which takes in T and outputs a string: 1)假设你有一个func,它接受T并输出一个字符串:

 Func<T, string> 

Can you transform that into a func that take in a T and returns a bool based on some logic (in this case if the returned string is empty (String.IsNullOrWhiteSpace)? 你能把它变成一个接受T的函数并根据某些逻辑返回一个bool(在这种情况下,如果返回的字符串为空(String.IsNullOrWhiteSpace)?

 Func<T, bool> 

2) Can you do the same thing if you are given an 如果给你一个,你可以做同样的事吗?

Expression<Func<T, string>>

and need to convert it to a 并需要将其转换为

Func<T, bool>

that returns true/false based on if the returned string is empty (String.IsNullOrWhiteSpace)? 返回true / false基于返回的字符串是否为空(String.IsNullOrWhiteSpace)?

Thanks 谢谢

for the first part you can even make some "higher"-order function: 对于第一部分,您甚至可以制作一些“更高”的顺序函数:



Func<A,C> MapFun<A,B,C>(Func<A,B> input, Func<B,C> transf)
{
   return a => transf(input(a));
}

use with 使用



Func <T,string> test = ...
var result = MapFun(test, String.IsNullOrWhiteSpace);

(I hope C# type type inference is working here) (我希望C#类型推断在这里工作)

If you define this as extension on Func it gets even easier: 如果您在Func上将其定义为扩展,则更容易:


public static class FuncExtension
{
    public static Func<A,C> ComposeWith<A,B,C>(this Func<A,B> input, Func<B,C> f)
    {
         return a => f(input(a));
    }
}

here is a very simple test: 这是一个非常简单的测试:


Func<int, string> test = i => i.ToString();
var result = test.ComposeWith(string.IsNullOrEmpty);

For the second one: I think you can compile the expression into a "real" Func and then use the above code. 对于第二个:我认为你可以将表达式编译成“真正的”Func,然后使用上面的代码。 see MSDN Docs on Expression.Compile 请参阅Expression.Compile上的MSDN文档

PS: renamed the function to better match it's intend (it's function composition) PS:重命名函数以更好地匹配它的意图(它的功能组成)

Could you not define it as a separate delegate: 你能不能把它定义为一个单独的委托:

Func<T, string> func1 = t => t.ToString();
Func<T, bool> func2 = t => string.IsNullOrEmpty(func1(t));

For the first part the technique is known as function composition ie you compose 2 functions to create a new function. 对于第一部分,该技术被称为函数组合,即您组成2个函数来创建新函数。 In your case you have a function Func<T,String> and another function (like string empty or null) which is of type Func<string,bool> , using function composition you can compose these two functions to create a new function of type Func<T,Bool> 在你的情况下,你有一个函数Func<T,String>和另一个函数(如字符串空或null),它的类型为Func<string,bool> ,使用函数组合你可以组合这两个函数来创建一个新的函数类型Func<T,Bool>

Most functional programming language have this composition of function already defined in their standard library or in the language itself. 大多数函数式编程语言都已经在其标准库或语言本身中定义了这种函数组合。 But it is no tough to create one for your language if the language supports functions as first class values. 但是,如果语言支持作为第一类值的函数,那么为您的语言创建一个并不困难。

In C# you can use the below function which will allow you to compose functions: 在C#中,您可以使用以下功能,这将允许您撰写功能:

public static Func<X,Z> Compose<X,Y,Z>(Func<X,Y> a, Func<Y,Z> b)
{
    return (v) => b(a(v));
}

To 1: Yes (You can also parametrize bool and string): 至1:是(您还可以参数化bool和string):

Func<T, bool> Compose<T>(Func<T, string> source, Func<string, bool>map)
{
    return x => map(source(x));
}

To 2: Yes, but you need to compile the expression first: 到2:是的,但是你需要先编译表达式:

Func<T, bool> Compose<T>(Expression<Func<T, string>> source, Func<string, bool> map)
{
    return x => compose(source.Compile(), map)
}

.Compile will compile the expression into a dynamic CLR method that you can invoke with the returned delegate. .Compile会将表达式编译为动态CLR方法,您可以使用返回的委托调用该方法。

You can use this code like this: 您可以像这样使用此代码:

Func<int, string> ts = i => i.ToString();
var result = Compose(ts, string.IsNullOrEmpty);

By the way, in this case you should really write a higher-order function. 顺便说一下,在这种情况下你应该写一个更高阶的函数。 What you are doing here (algebraically) is composing monoids. 你在这里(代数)做的是组成幺半群。 Remember function composition ? 记得功能构成吗? f . g := f(g(x)) f . g := f(g(x)) is what you are doing here. f . g := f(g(x))就是你在这里做的。

Think of source as g:A->B and map as f:B->C (where A,B and C are sets) so the result of f . g 将源视为g:A->B并映射为f:B->C (其中A,B和C为集合),因此f . g的结果f . g f . g is h:A->C . f . gh:A->C By the way, the . 顺便说一句. operator is often build into functional programming languages, such as Haskell and achieves the same thing as your compose function (but with cleaner syntax). 运算符通常构建为函数式编程语言,例如Haskell,并且与compose函数实现相同的功能(但语法更清晰)。

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

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