c# sort list




使用LINQ维护订单 (4)

任何“按组”或“按订单”都可能会改变订单。

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


你真的在谈论SQL,还是关于数组? 换句话说,你是使用LINQ to SQL还是LINQ to Objects?

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

如果你转换为不同的数据结构,例如使用ToLookup或ToDictionary,我不认为顺序在这一点上保留 - 但是这有点不同。 (我相信,虽然映射到同一个键的值的顺序被保留用于查找。)


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

对于Enumerable方法(LINQ to Objects,适用于List<T> ),您可以依赖SelectWhereGroupBy返回的元素的顺序。 对于像ToDictionaryDistinct这样天生无序的事物,情况并非如此。

来自Enumerable.GroupBy文档:

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

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

来源: LINQ的Enumerable方法保持元素的相对顺序吗?


我检查了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按该顺序枚举第一个和第二个,并产生尚未产生的每个元素。

编辑:我已经移动了基于这个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;
    }






data-structures