使用Linq时按原始索引重新排序

本文关键字:新排序 排序 索引 Linq 原始 使用 | 更新日期: 2023-09-27 17:58:51

我四处寻找这个问题的解决方案,尽管我发现了类似的问题,但我找不到这个特定问题的答案。我已经概括了这个问题,但它是这样的:

我有以下内部[]

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

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

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

使用Linq时按原始索引重新排序

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

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();

使用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博客上阅读更多。

无需进行任何排序,订单将得到维护。

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