394

我在有序数组上使用 LINQ to Objects 指令。我不应该执行哪些操作来确保数组的顺序没有改变?

4

6 回答 6

710

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

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

  • 可枚举
  • 投掷
  • 康卡特
  • 选择
  • 数组
  • 列表

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

  • 清楚的
  • 除了
  • 相交
  • 类型
  • 前置(.net 4.7.1 中的新功能)
  • 跳过
  • 跳过时
  • TakeWhile
  • 在哪里
  • Zip(.net 4 中的新功能)

Destroys Order - 我们不知道预期的结果是什么顺序。

  • 到字典
  • 去查查看

明确重新定义顺序 - 使用这些来更改结果的顺序

  • 排序依据
  • 按降序排列
  • 逆转
  • 然后通过
  • 然后降序

根据一些规则重新定义订单。

  • GroupBy - IGrouping 对象的生成顺序基于 source 中生成每个 IGrouping 的第一个键的元素的顺序。分组中的元素按照它们在源中出现的顺序产生。
  • GroupJoin - GroupJoin 保留外部元素的顺序,并且对于外部的每个元素,匹配元素从内部开始的顺序。
  • Join - 保留外部元素的顺序,并且对于这些元素中的每一个,保留内部匹配元素的顺序。
  • SelectMany - 对于 source 的每个元素,调用选择器并返回一系列值。
  • Union - 当枚举此方法返回的对象时,Union 按该顺序枚举第一个和第二个,并产生每个尚未产生的元素。

编辑:我已经将 Distinct 移动到 Preserving order based on this implementation

    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;
    }
于 2008-10-15T13:51:27.133 回答
38

您实际上是在谈论 SQL,还是在谈论数组?换句话说,您使用的是 LINQ to SQL 还是 LINQ to Objects?

LINQ to Objects 运算符实际上并未更改其原始数据源——它们构建了由数据源有效支持的序列。改变排序的唯一操作是 OrderBy/OrderByDescending/ThenBy/ThenByDescending - 即使这样,对于相同排序的元素,这些操作也是稳定的。当然,很多操作都会过滤掉一些元素,但是返回的元素会按照相同的顺序排列。

如果您转换为不同的数据结构,例如使用 ToLookup 或 ToDictionary,我不相信此时会保留顺序 - 但无论如何这有些不同。(但我相信,映射到同一键的值的顺序会保留以供查找。)

于 2008-10-15T12:24:00.523 回答
8

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

[编辑:正如乔恩说得更清楚;LINQ一般会创建一个序列,不理会原始数据]

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

但最常见的事情(选择、位置、跳过、采取)应该没问题。

于 2008-10-15T12:25:09.333 回答
5

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

对于Enumerable方法(适用于 的 LINQ to Objects List<T>),您可以依赖 、 或 所返回的元素SelectWhere顺序GroupByToDictionary对于本质上无序的事物,例如or ,情况并非如此Distinct

来自Enumerable.GroupBy文档:

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

这不一定适用于IQueryable扩展方法(其他 LINQ 提供程序)。

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

于 2014-06-11T21:04:43.257 回答
2

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

于 2008-10-15T12:53:11.447 回答
0

这里的问题是专门指LINQ-to-Objects。

如果您使用的是 LINQ-to-SQL,则那里没有顺序,除非您使用以下命令强加:

mysqlresult.OrderBy(e=>e.SomeColumn)

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

于 2019-05-19T09:24:16.407 回答