我一直在寻找解决这个问题的方法,虽然我发现了类似的问题,但我找不到这个特定问题的答案。我已经概括了这个问题,但它的情况如下:
我有以下 int[]
[423]
[234]
[5]
[79]
[211]
[1001]
我想使用 linq 仅选择小于 200 或大于 300 的条目,然后按原始数组索引排序,以保证最终数组为:
[423]
[5]
[79]
[1001]
当您过滤具有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;
}
在乔恩博客上阅读更多信息。
LINQ to object 保留了选择的顺序,所以一个简单的 where 子句就可以完成这项工作。
在 PLINQ 中,目标是在保持正确性的同时最大化性能。查询应尽可能快地运行,但仍会产生正确的结果。在某些情况下,正确性需要保留源序列的顺序;但是,排序可能在计算上很昂贵。因此,默认情况下,PLINQ 不保留源序列的顺序。在这方面,PLINQ 类似于 LINQ to SQL,但与 LINQ to Objects 不同,后者确实保留了排序。
但如果你愿意,你可以选择index
带有值的,稍后OrderBy
使用index
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();
无需进行任何排序,将保持顺序。
var someInts = new int[] { 423, 234, 5, 79, 211, 1001 };
var filteredInts = someInts.Where(i => i < 200 || i > 300);
// filteredInts = [423, 5, 79, 1001]