【问题标题】:Reorder by original index when using Linq使用 Linq 时按原始索引重新排序
【发布时间】:2013-02-12 10:26:26
【问题描述】:

我一直在寻找解决这个问题的方法,虽然我发现了类似的问题,但我找不到这个特定问题的答案。我已经概括了这个问题,但情况如下:

我有以下 int[]

[423]
[234]
[5]
[79]
[211]
[1001]

我想使用 linq 只选择小于 200 或大于 300 的条目,然后按原始数组索引排序,以保证最终数组为:

[423]
[5]
[79]
[1001]

【问题讨论】:

标签: c# linq


【解决方案1】:

LINQ to object 保留了选择的顺序,所以一个简单的 where 子句就可以完成这项工作。

Order Preservation in PLINQ

在 PLINQ 中,目标是在保持正确性的同时最大限度地提高性能。查询应尽可能快地运行,但仍会产生正确的结果。在某些情况下,正确性需要保留源序列的顺序;但是,排序可能在计算上很昂贵。因此,默认情况下,PLINQ 不保留源序列的顺序。在这方面,PLINQ 类似于 LINQ to SQL,但不同于保留顺序的 LINQ to Objects

但如果你愿意,你可以选择带有值的index,然后在index上使用OrderBy

int[] array = new [] 
{
    423,234,5,79,211,1001
};


 var sortedArray =  array.Select((r, i) => new { value = r, index = i })
                         .Where(t => t.value < 200 || t.value > 300)
                         .OrderBy(o => o.index)
                         .Select(s => s.value).ToArray();

【讨论】:

    【解决方案2】:

    当您使用Enumerable.Where 过滤对象时,会保留原始顺序。 MSDN:

    LINQ to Objects,确实保留了排序

    再说几句。您可以将Where 视为 foreach 循环中的简单过滤元素,它以与进入循环的顺序完全相同的顺序逐一返回项目。像这样:

    public IEnumerable<T> Where(this IEnumerable<T> sequence, Func<T,bool> predicate)
    {
        foreach(var item in sequence)
           if (predicate(item))
               yield return item;
    }
    

    阅读更多Jon blog

    【讨论】:

      【解决方案3】:

      无需进行任何排序,将保持顺序。

      var someInts = new int[] { 423, 234, 5, 79, 211, 1001 };
      var filteredInts = someInts.Where(i => i < 200 || i > 300);
      
      // filteredInts = [423, 5, 79, 1001]
      

      【讨论】:

      • 我似乎发现,当数组为 v.large 时,有时订单不会被保留。我的 linq 表达式非常复杂,但如果我能解决这个简单的例子,那么它就解决了我的主要问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-16
      • 1970-01-01
      • 2015-03-09
      • 2021-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多