我有一个有序的枚举数组,IorderedEnumerable<T>[] foo我想将它展平,以便有序的枚举foo按照它们存储在数组中的顺序连接在一起.
例如{{1,2,3},{4,5},{6}} => {1,2,3,4,5,6}
我可以这样做IOrderedEnumerable<T> bar = foo.SelectMany(x => x);,或者LINQ不能保证在展平时如何处理订单?
列表(由IEnumerable<T>.net 表示)以及两个操作组成一个monad,它必须遵守monad法则.这两个操作中给出了不同的语言不同的名字,维基百科的文章使用哈斯克尔这就要求他们return和>>=(称为"绑定").C#调用>>= SelectMany并没有内置函数return.这些名称并不重要,重要的是类型.专门为IEnumerable<T>这些是:
Return :: T -> IEnumerable<T>
SelectMany :: IEnumerable<T> -> Func<T, IEnumerable<U>> -> IEnumerable<U>
Run Code Online (Sandbox Code Playgroud)
Return 简单地返回包含给定元素的1元素序列,例如
public static IEnumerable<T> Return<T>(T item)
{
return new[] { item };
}
Run Code Online (Sandbox Code Playgroud)
SelectMany已经实施为Enumerable.SelectMany:
public static IEnumerable<U> SelectMany<T, U>(IEnumerable<T> seq, Func<T, IEnumerable<U>> f) { ... }
Run Code Online (Sandbox Code Playgroud)
SelectMany 采用输入序列和函数,该函数为输入序列的每个项生成另一个序列,并将得到的序列序列展平为一个.
在C#重述前两个monad法则我们有:
左派身份
Func<T, IEnumerable<U>> f = ...
Return(x).SelectMany(f) == f(x)
Run Code Online (Sandbox Code Playgroud)
正确的身份
IEnumerable<T> seq = ...
seq.SelectMany(Return) == seq
Run Code Online (Sandbox Code Playgroud)
通过正确的身份定律,SelectMany必须Func<T, IEnumerable<U>>根据输入元素的顺序展平每个生成的序列.
假设它以相反的顺序扁平化它们,例如
new[] { 1, 2 }.SelectMany(i => new[] { i, -i }) == new[] { 2, -2, 1, -1 }
Run Code Online (Sandbox Code Playgroud)
然后
var s = new[] { 1, 2 }
s.SelectMany(Return) == new[] { 2, 1 } != s
Run Code Online (Sandbox Code Playgroud)
这不符合所要求的权利身份法.
| 归档时间: |
|
| 查看次数: |
2125 次 |
| 最近记录: |