LINQ是否保证可以通过SelectMany订购? [英] LINQ Guarantees Ordering with SelectMany?

查看:60
本文介绍了LINQ是否保证可以通过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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆