对于一个项目,我将不得不经常使用包含大量数据的数组的N个最后一个元素。获得数组N的最后一个元素的最有效方法
我试图让
myArray.Skip(myArray.Length - toTake).Take(toTake)
但我发现它缓慢。
我比起来,这样的:
public static int[] TakeLast(this int[] inputArray, int count)
{
int[] returnArray = new int[count];
int startIndex = Math.Max(inputArray.Count() - count, 0);
unsafe
{
fixed (int* itemArrayPtr = &(inputArray[startIndex]))
{
fixed (int* arrayPtr = &(returnArray[0]))
{
int* itemValuePtr = itemArrayPtr;
int* valuePtr = arrayPtr;
for (int i = 0; i < count; i++)
{
*valuePtr++ = *itemValuePtr++;
}
}
}
}
return returnArray;
}
这种运作良好,这是不能通用的(我希望这可以为任何基本类型(整型,浮点,双,...)工作
。有没有一种方法,以获得具有通用/ LINQ/...方法相当的性能?我不需要做它的工作原理上的IEnumerable,阵列是对我来说足够。
编辑 我目前正在测试所有我thods你给我的,现在它的Array.Copy这似乎是更快:
Generating array for 100000000 elements.
SkipTake: 00:00:00.3009047
Unsafe: 00:00:00.0006289
Array.Copy: 00:00:00.0000012
Buffer.BlockCopy: 00:00:00.0001860
Reverse Linq: 00:00:00.2201143
Finished
'new T [count]'后面跟着'Array.Copy'?顺便说一句,以什么方式演示'Enumerable.Skip' /'Enumerable.Take'的速度很慢的短程序会很好,这将使实际测试建议的替代品成为可能,而不是主要猜测。 – hvd
是的,我会认为Array.Copy()会和指针算术一样快,因为它可能使用memcpy等效实现。 –
我不认为它会产生明显的差异,但是您对'Take()'的调用是不必要的。如果您只是使用'myArray.Skip(myArray.Length - toTake)',性能是否会提高很多? – BACON