用LINQ维护秩序

我在一个有序数组上使用LINQ to Objects指令。 我不应该做哪些操作来确保数组的顺序没有改变?< / p >

66365 次浏览

你是在谈论SQL,还是数组?换句话说,你使用的是LINQ To SQL还是LINQ To对象?

LINQ to Objects操作符实际上并不改变它们的原始数据源——它们构建的序列得到了数据源的有效支持。唯一改变顺序的操作是orderderby / orderbydescent /ThenBy/ thenbydescent——即使这样,这些操作对于相同顺序的元素也是稳定的。当然,许多操作将过滤掉一些元素,但返回的元素将是相同的顺序。

如果转换为不同的数据结构,例如使用ToLookup或ToDictionary,我不相信在这一点上顺序是被保留的——但无论如何,这有点不同。(不过我相信,映射到相同键的值的顺序在查找时是保留的。)

如果你正在处理一个数组,听起来像是你在使用LINQ-to-Objects,而不是SQL;你能否证实?大多数LINQ操作不会对任何东西重新排序(输出将与输入的顺序相同)-所以不要应用另一种排序(OrderBy[降序]/ThenBy[降序])。

[编辑:乔恩说得更清楚;LINQ通常创建序列,而不影响原始数据]

注意,将数据推入Dictionary<,> (ToDictionary)将打乱数据,因为字典不尊重任何特定的排序顺序。

但大多数常见的事情(选择,在哪里,跳过,采取)应该是好的。

任何“group by”或“order by”都可能改变顺序。

我检查了System.Linq.Enumerable的方法,丢弃了任何返回非ienumerable结果的方法。我检查了每一个的注释,以确定结果的顺序与源的顺序有什么不同。

绝对维护秩序。可以通过索引将源元素映射到结果元素

  • AsEnumerable
  • Concat
  • 选择
  • ToArray
  • ToList

保持秩序。元素被过滤或添加,但不重新排序。

  • 截然不同的
  • 除了
  • 相交
  • 减低
  • Prepend (.net 4.7.1新增功能)
  • 跳过
  • SkipWhile
  • TakeWhile
  • 在哪里
  • Zip (.net 4中的新功能)

破坏秩序——我们不知道结果的顺序。

  • ToDictionary
  • ToLookup

显式重定义顺序-使用这些来改变结果的顺序

  • OrderBy
  • OrderByDescending
  • 反向
  • ThenBy
  • ThenByDescending

根据某些规则重新定义Order。

  • GroupBy——根据源中产生每个IGrouping的第一个键的元素的顺序产生IGrouping对象。分组中的元素是按照它们在源代码中出现的顺序生成的。
  • GroupJoin—GroupJoin保留outer元素的顺序,对于outer的每个元素,保留来自inner的匹配元素的顺序。
  • Join -保留外层元素的顺序,并且对于这些元素中的每个元素,内部的匹配元素的顺序。
  • SelectMany -对于source的每个元素,都会调用selector并返回一个值序列。
  • Union——当枚举此方法返回的对象时,Union将按此顺序枚举第一个和第二个对象,并生成尚未生成的每个元素。

编辑:我已经根据这个实现将Distinct移动到保留顺序。

    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;
}

我在一个类似的问题中找到了一个很好的答案,它引用了官方文件。引用一下:

对于Enumerable方法(LINQ to Objects,适用于List<T>),可以依赖SelectWhereGroupBy返回的元素顺序。对于像ToDictionaryDistinct这样固有无序的东西则不是这样。

来自可列举的。GroupBy文档:

IGrouping<TKey, TElement>对象的生成顺序基于源中产生每个IGrouping<TKey, TElement>的第一个键的元素的顺序。分组中的元素按照它们在source中出现的顺序产生。

这对于IQueryable扩展方法(其他LINQ提供者)不一定是正确的。

来源:LINQ's枚举方法是否保持元素的相对顺序?

这里的问题特别指的是LINQ-to-Objects。

如果你使用LINQ-to-SQL而不是没有秩序,除非你强加一个像这样的东西:

mysqlresult.OrderBy(e=>e.SomeColumn)

如果不对LINQ-to-SQL执行此操作,则后续查询的结果顺序可能会不同,即使是相同的数据,这可能会导致间歇性错误。