有时您没有索引的奢侈,或者您可能想要反转 Linq 查询的结果,或者您可能不想修改源集合,如果这些都是真的,Linq 可以提供帮助你。
使用匿名类型和 Linq Select 的 Linq 扩展方法为 Linq OrderByDescending 提供排序键;
public static IEnumerable<T> Invert<T>(this IEnumerable<T> source)
{
var transform = source.Select(
(o, i) => new
{
Index = i,
Object = o
});
return transform.OrderByDescending(o => o.Index)
.Select(o => o.Object);
}
用法:
var eable = new[]{ "a", "b", "c" };
foreach(var o in eable.Invert())
{
Console.WriteLine(o);
}
// "c", "b", "a"
之所以命名为“Invert”,是因为它是“Reverse”的同义词,并且可以消除 List Reverse 实现的歧义。
也可以反转集合的某些范围,因为 Int32.MinValue 和 Int32.MaxValue 超出了任何集合索引的范围,我们可以将它们用于排序过程;如果元素索引低于给定范围,则为其分配 Int32.MaxValue,以便在使用 OrderByDescending 时其顺序不会改变,类似地,索引大于给定范围的元素将分配 Int32.MinValue,以便它们出现在订购过程的末尾。给定范围内的所有元素都被分配了它们的正常索引并相应地反转。
public static IEnumerable<T> Invert<T>(this IEnumerable<T> source, int index, int count)
{
var transform = source.Select(
(o, i) => new
{
Index = i < index ? Int32.MaxValue : i >= index + count ? Int32.MinValue : i,
Object = o
});
return transform.OrderByDescending(o => o.Index)
.Select(o => o.Object);
}
用法:
var eable = new[]{ "a", "b", "c", "d" };
foreach(var o in eable.Invert(1, 2))
{
Console.WriteLine(o);
}
// "a", "c", "b", "d"
我不确定这些 Linq 实现与使用临时 List 包装集合以进行逆向相比对性能的影响。
在撰写本文时,我还不知道 Linq 自己的 Reverse 实现,不过,解决这个问题很有趣。
https://msdn.microsoft.com/en-us/library/vstudio/bb358497(v=vs.100).aspx