Answers:
我检查了System.Linq.Enumerable的方法,丢弃了所有返回非IEnumerable结果的方法。我检查了每个注释,以确定结果的顺序与源顺序之间的差异。
绝对保留订单。您可以按索引将源元素映射到结果元素
保留订单。元素被过滤或添加,但不重新排序。
销毁订单-我们不知道期望的订单顺序。
明确地重新定义订单-使用这些来更改结果的顺序
根据一些规则重新定义订单。
编辑:基于此实现,我已将Distinct移至Preserving order 。
private static IEnumerable<TSource> DistinctIterator<TSource>
(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in source)
if (set.Add(element)) yield return element;
}
Distinct
方法)只是要说“未排序”,而不是“按不可预测的顺序”。我会说Distinct
属于上面的过滤类别Where
。
您实际上是在谈论SQL还是数组?换句话说,您是使用LINQ to SQL还是LINQ to Objects?
LINQ to Objects运算符实际上并没有更改其原始数据源,而是建立了由数据源有效支持的序列。唯一会更改顺序的操作是OrderBy / OrderByDescending / ThenBy / ThenByDescending-即便如此,那些操作对于相同顺序的元素也是稳定的。当然,许多操作会过滤掉某些元素,但是返回的元素将以相同的顺序排列。
如果您转换为其他数据结构(例如,使用ToLookup或ToDictionary),则我不认为此时会保留顺序-但这还是有些不同。(我相信,映射到相同键的值的顺序会保留,以供查找。)
GroupBy
随后SelectMany
会给者皆分组的结果,而不是在按键的升序...这将使他们在最初发生的按键顺序。
list<x> {a b c d e f g}
如果c,d,e都具有相同的键,则结果序列将包含c,d,e 并排 且顺序为c,d,e。我似乎找不到基于MS的绝对答案。
如果您正在处理数组,听起来好像您使用的是LINQ-to-Objects,而不是SQL。你可否确认?大多数LINQ操作不会重新排序任何东西(输出将与输入顺序相同)-因此请勿应用其他排序方式(OrderBy [Descending] / ThenBy [Descending])。
[编辑:正如乔恩所说的那样;LINQ通常会创建一个新序列,而将原始数据保留下来]
请注意,将数据推送到Dictionary<,>
(ToDictionary)中会扰乱数据,因为字典不遵守任何特定的排序顺序。
但是最常见的事情(选择,哪里,跳过,取走)应该没问题。
ToDictionary()
做任何承诺,而是在实践中保持输入订单(直到您从其中删除某些内容为止)。我并不是说要依靠它,但是“加扰”似乎是不准确的。
我在引用官方文档的类似问题中找到了一个很好的答案。引用一下:
对于Enumerable
方法(LINQ到对象,它适用于List<T>
),你可以依赖通过返回的元素的顺序Select
,Where
或GroupBy
。对于本质上无序的事物(例如ToDictionary
或),情况并非如此Distinct
。
从Enumerable.GroupBy文档中:
的
IGrouping<TKey, TElement>
对象被产生在该基于产生的每个的所述第一密钥在源中的元素的顺序上的顺序IGrouping<TKey, TElement>
。分组中的元素按它们出现的顺序产生source
。
对于IQueryable
扩展方法(其他LINQ提供程序)不一定是正确的。