SelectMany将遍历一个对象树:
class Agency { List<Employees> Staff }
IEnumerable<Agency> Agencies
IEnumerable<Employee> =
from anAgency in Agencies
from anEmployee in anAgency.Staff.
select anEmployee;
通常情况下,我会先选择代理商,然后使用员工的内部实例来获取员工。但是在政府关闭的情况下,我只想列出每个人,看谁能覆盖。
在这种不适合我的对象模型的情况下,我可以使用SelectMany来任意遍历树。
你怎么称呼这个遍历?交叉加入?这不是因为加入已经隐含在原子能机构对象的工作人员组成中。
绑定吗?我对bind一无所知。
除了选择,很多之外,没有别的名字吗?!
答案 0 :(得分:47)
SelectMany
对应于Scala中的Haskell (>>=)
或flatMap
中的绑定。 Haskell中>>=
的签名是:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
所以bind是一个用于从另一个构造一个monadic值的操作。
如果上述签名中的C#m
为IEnumerable
,IObservable
,IQueryable
等。对于IEnumerable
,SelectMany
为因此
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还必须支持另外两个操作map
和join
。
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
与其他语言中的bind
或flatMap
相对应。绑定不只是扁平化,而是可以看作是转换,随后是嵌套的monadic值的扁平化(例如IEnumerable<T>
的情况下的序列)。当前的linq扩展中不存在join
的{{1}}。
答案 1 :(得分:4)
在.NET世界中,它通常被称为“扁平化”,如果这就是你所要求的。它将二维结果集展平为单个维度。