LINQ是否保证可以通过SelectMany订购? [英] LINQ Guarantees Ordering with SelectMany?
问题描述
我有一个有序的可枚举数组IorderedEnumerable<T>[] foo
,我想对其进行展平,以使foo
的有序可枚举数组按照存储在数组中的顺序串联在一起.
I have an array of ordered enumerables IorderedEnumerable<T>[] foo
and I want to flatten it so that the ordered enumerables of foo
are concatenated together in the order they are stored in the array.
例如{{1,2,3},{4,5},{6}} => {1,2,3,4,5,6}
For example {{1, 2, 3}, {4, 5}, {6}} => {1, 2, 3, 4, 5, 6}
我可以通过IOrderedEnumerable<T> bar = foo.SelectMany(x => x);
执行此操作吗,还是LINQ不保证展平时如何处理订单?
Can I do this by IOrderedEnumerable<T> bar = foo.SelectMany(x => x);
, or does LINQ not guarantee how order is handled when flattening?
推荐答案
列表(由.net中的IEnumerable<T>
表示)以及两个操作组成一个monad,必须遵循>>= SelectMany
,并且没有return
的内置函数.名称并不重要,重要的是类型.专门针对IEnumerable<T>
的是:
Lists (represented by IEnumerable<T>
in .net) along with two operations form a monad, which must obay the monad laws. These two operations are given different names in different languages, the wikipedia article uses Haskell which calls them return
and >>=
(called 'bind'). C# calls >>=
SelectMany
and does not have a built-in function for return
. The names are unimportant however and what matters is the types. Specialised for IEnumerable<T>
these are:
Return :: T -> IEnumerable<T>
SelectMany :: IEnumerable<T> -> Func<T, IEnumerable<U>> -> IEnumerable<U>
Return
仅返回包含给定元素的1元素序列,例如.
Return
simply returns a 1-element sequence containing the given element e.g.
public static IEnumerable<T> Return<T>(T item)
{
return new[] { item };
}
SelectMany
已被实现为Enumerable.SelectMany
:
public static IEnumerable<U> SelectMany<T, U>(IEnumerable<T> seq, Func<T, IEnumerable<U>> f) { ... }
SelectMany
接受一个输入序列和一个函数,该函数为输入序列的每一项生成另一个序列,并将所得序列序列展平为一个序列.
SelectMany
takes an input sequence and a function which generates another sequence for each item of the input sequence and flattens the resulting sequence of sequences into one.
重新计算C#中的前两个monad定律:
Restating the first two monad laws in C# we have:
左身份
Func<T, IEnumerable<U>> f = ...
Return(x).SelectMany(f) == f(x)
右身份
IEnumerable<T> seq = ...
seq.SelectMany(Return) == seq
根据正确的身份法,SelectMany
必须根据输入元素的顺序展平Func<T, IEnumerable<U>>
生成的每个序列.
By the right identity law, SelectMany
must flatten each sequence generated by the Func<T, IEnumerable<U>>
according to the order of the input elements.
假设它以相反的顺序将它们展平.
Assume it flattened them in reverse order e.g.
new[] { 1, 2 }.SelectMany(i => new[] { i, -i }) == new[] { 2, -2, 1, -1 }
然后
var s = new[] { 1, 2 }
s.SelectMany(Return) == new[] { 2, 1 } != s
不符合所需的权利身份法.
which would not satisfy the right-identity law required.
这篇关于LINQ是否保证可以通过SelectMany订购?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!