LINQ SelectMany是绑定?

时间:2013-10-11 15:28:58

标签: c# linq

SelectMany将遍历一个对象树:

class Agency { List<Employees> Staff }

IEnumerable<Agency> Agencies

IEnumerable<Employee> =  
from anAgency in Agencies  
from anEmployee in anAgency.Staff. 
select anEmployee; 

通常情况下,我会先选择代理商,然后使用员工的内部实例来获取员工。但是在政府关闭的情况下,我只想列出每个人,看谁能覆盖。

在这种不适合我的对象模型的情况下,我可以使用SelectMany来任意遍历树。

你怎么称呼这个遍历?交叉加入?这不是因为加入已经隐含在原子能机构对象的工作人员组成中。

绑定吗?我对bind一无所知。

除了选择,很多之外,没有别的名字吗?!

2 个答案:

答案 0 :(得分:47)

C#中的

SelectMany对应于Scala中的Haskell (>>=)flatMap中的绑定。 Haskell中>>=的签名是:

(>>=) :: Monad m => m a -> (a -> m b) -> m b

所以bind是一个用于从另一个构造一个monadic值的操作。

如果上述签名中的C#mIEnumerableIObservableIQueryable等。对于IEnumerableSelectMany为因此

IEnumerable<A> -> (A -> IEnumerable<B>) -> IEnumerable<B>

或在C#中

public static IEnumerable<B> SelectMany<A, B>(this IEnumerable<A> first, Func<A, IEnumerable<B>> selector)

bind的含义取决于monad类型,对于IEnumerable,输入序列中的每个元素用于创建一个新序列,并且生成的序列序列被展平以产生输出序列。

还有另一种结合方式可以使其更清晰。虽然monad通常是根据bind的实现来描述的,但monad还必须支持另外两个操作mapjoin

map对应于C#中的Select,如下所示:

map :: Monad m => (a -> b) -> (ma -> m b)

因此它是一种'结构保留'方法,可以在monadic值上提升常规函数。

join的类型为

join :: Monad m => m m a -> m a

所以join用于展平嵌套的monadic值。在C#中,这看起来像

public static IEnumerable<A> Join<A>(this IEnumerable<IEnumerable<A>> nested)

bind可以在地图和连接方面实施

m >>= f = join (map f m)

所以要回答原始问题,SelectMany与其他语言中的bindflatMap相对应。绑定不只是扁平化,而是可以看作是转换,随后是嵌套的monadic值的扁平化(例如IEnumerable<T>的情况下的序列)。当前的linq扩展中不存在join的{​​{1}}。

答案 1 :(得分:4)

在.NET世界中,它通常被称为“扁平化”,如果这就是你所要求的。它将二维结果集展平为单个维度。