SelectMany将遍历一个对象树:
class Agency { List<Employees> Staff }
IEnumerable<Agency> Agencies
IEnumerable<Employee> =
from anAgency in Agencies
from anEmployee in anAgency.Staff.
select anEmployee;
Run Code Online (Sandbox Code Playgroud)
通常,我会先选择代理商,然后使用员工的内部实例来获取员工.但是在政府关闭的情况下,我只想列出每个人,看谁能覆盖.
在这种不适合我的对象模型的罕见情况下,我可以使用SelectMany来任意遍历树.
你怎么称呼这个遍历?交叉加入?这不是因为加入已经隐含在原子能机构对象的工作人员组成中.
它绑定了吗?我对bind一无所知.
除了Select之外没有别的名字吗?
Lee*_*Lee 48
SelectMany
在C#中对应于Haskell (>>=)
或flatMap
Scala中的绑定.>>=
Haskell 的签名是:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
所以bind是一个用于从另一个构造一个monadic值的操作.
在C#的情况下m
在上述签名是IEnumerable
,IObservable
,IQueryable
等.IEnumerable
,SelectMany
因此是
IEnumerable<A> -> (A -> IEnumerable<B>) -> IEnumerable<B>
Run Code Online (Sandbox Code Playgroud)
或者在C#中
public static IEnumerable<B> SelectMany<A, B>(this IEnumerable<A> first, Func<A, IEnumerable<B>> selector)
Run Code Online (Sandbox Code Playgroud)
bind的含义取决于monad类型,对于IEnumerable,输入序列中的每个元素用于创建新序列,并且生成的序列序列被展平以产生输出序列.
还有另一种结合方式可以使其更清晰.虽然monad通常用它们的bind实现来描述,但monad也必须支持另外两个操作,map
并且join
.
map
对应于C#中的Select,看起来像:
map :: Monad m => (a -> b) -> (ma -> m b)
Run Code Online (Sandbox Code Playgroud)
因此它是一种"结构保持"方式,可以在monadic值上提升常规函数.
join
有类型
join :: Monad m => m m a -> m a
Run Code Online (Sandbox Code Playgroud)
所以join用于展平嵌套的monadic值.在C#中,这看起来像
public static IEnumerable<A> Join<A>(this IEnumerable<IEnumerable<A>> nested)
Run Code Online (Sandbox Code Playgroud)
bind
可以用map和join来实现
m >>= f = join (map f m)
Run Code Online (Sandbox Code Playgroud)
所以回答原始问题,SelectMany
对应于bind
或flatMap
用其他语言.绑定不仅仅是扁平化,而是可以看作是一种转换,随后是嵌套的monadic值的扁平化(例如,序列中的序列IEnumerable<T>
).join
for IEnumerable<T>
当前的linq扩展中不存在.