用LINQ保持秩序
我在有序数组上使用LINQ to Objects指令。 我不应该做哪些操作来确保数组的顺序没有改变?
我检查了System.Linq.Enumerable的方法,放弃了返回非IEnumerable结果的东西。 我检查了每个的评论,以确定结果的顺序将如何与来源的顺序不同。
完全保留订单。 您可以通过索引将源元素映射到结果元素
- AsEnumerable
- 投
- CONCAT
- 选择
- ToArray的
- ToList
保留订单。 元素被过滤,但不被重新排序。
- 不同
- 除
- 相交
- OfType
- 跳跃
- SkipWhile
- 采取
- TakeWhile
- 哪里
- Zip(新的.net 4)
破坏秩序 – 我们不知道以什么顺序期望的结果。
- ToDictionary
- 去查查看
重新定义顺序显式 – 使用这些来改变结果的顺序
- 排序依据
- OrderByDescending
- 相反
- ThenBy
- ThenByDescending
根据一些规则重新定义订单。
- GroupBy – IGrouping对象按照产生每个IGrouping的第一个键的源元素的顺序产生。 分组中的元素按照它们在源代码中出现的顺序排序。
- GroupJoin – GroupJoin保留外部元素的顺序,并且对于每个外部元素,从内部匹配元素的顺序。
- 加入 – 保留外部元素的顺序,并且对于这些元素中的每一个,内部匹配元素的顺序。
- SelectMany – 对于源的每个元素,调用选择器并返回一系列值。
- Union – 枚举此方法返回的对象时,Union按此顺序枚举第一个和第二个,并产生尚未产生的每个元素。
编辑:我已经移动了基于这个实现保持秩序不同。
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; }
你是在谈论SQL还是数组? 换句话说,你使用LINQ to SQL或者LINQ to Objects吗?
LINQ to Objects运算符实际上并没有改变它们的原始数据源 – 它们构建了由数据源有效支持的序列。 唯一改变顺序的操作是OrderBy / OrderByDescending / ThenBy / ThenByDescending – 即使如此,那些对于相同顺序的元素也是稳定的。 当然,很多操作会过滤掉一些元素,但是返回的元素将会按照相同的顺序排列。
如果你转换为不同的数据结构,例如使用ToLookup或ToDictionary,我不相信顺序在这一点上保留 – 但是这有点不同。 (我相信,映射到同一个键的值的顺序被保留用于查找。)
如果你正在处理一个数组,这听起来像你正在使用LINQ到对象,而不是SQL; 你可否确认? 大多数LINQ操作不会重新排序(输出的顺序与输入顺序相同),所以不要使用其他排序(OrderBy [Descending] / ThenBy [Descending])。
正如Jon所说的更清楚一样。 LINQ通常会创建一个新的序列,只保留原始数据]
请注意,将数据推送到Dictionary<,>
(ToDictionary)将扰乱数据,因为字典不尊重任何特定的排序顺序。
但最常见的东西(选择,在哪里,跳过,采取)应该没问题。
任何“按组”或“按顺序”都可能会改变顺序。
我在一个引用官方文档的类似问题中找到了一个很好的答案。 引用它:
对于Enumerable
方法(LINQ to Objects,适用于List<T>
),您可以依赖于Select
, Where
或GroupBy
返回的元素的顺序。 对于像ToDictionary
或Distinct
这样天生无序的事物,情况并非如此。
从Enumerable.GroupBy文档:
IGrouping<TKey, TElement>
对象按照产生每个IGrouping<TKey, TElement>
的第一个键的源元素的顺序排序。 分组中的元素按照它们在source
出现的顺序排序。
对于IQueryable
扩展方法(其他LINQ提供者),这不一定是正确的。
来源: 做LINQ的枚举方法保持元素的相对顺序?