这个怎么样?应该相当快:
public static class ArrayExt
{
public static T[] TakeLast<T>(this T[] inputArray, int count) where T: struct
{
count = Math.Min(count, inputArray.Length);
int size = Marshal.SizeOf(typeof(T));
T[] result = new T[count];
Buffer.BlockCopy(inputArray, (inputArray.Length-count)*size, result, 0, count*size);
return result;
}
}
(我认为这比Array.Copy()在原始类型方面更快。但我不会把它视为理所当然——5分钟内会回来进行一些计时。;)
[编辑]计时显示Array.Copy()速度类似,但结果因运行和数组大小而异。
这是一些示例代码:
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
namespace Demo
{
internal class Program
{
private void run()
{
const int ARRAY_SIZE = 10000;
var array = Enumerable.Range(0, ARRAY_SIZE).Select(x => x).ToArray();
Stopwatch sw = new Stopwatch();
const int COUNT = 100000;
for (int i = 0; i < 8; ++i)
{
sw.Restart();
for (int j = 0; j < COUNT; ++j)
array.TakeLastViaArrayCopy(ARRAY_SIZE/2);
Console.WriteLine("TakeLastViaArrayCopy took " + sw.Elapsed);
sw.Restart();
for (int j = 0; j < COUNT; ++j)
array.TakeLastViaBlockCopy(ARRAY_SIZE/2);
Console.WriteLine("TakeLastViaBlockCopy took " + sw.Elapsed);
Console.WriteLine();
}
}
private static void Main()
{
new Program().run();
}
}
public static class ArrayExt
{
public static T[] TakeLastViaBlockCopy<T>(this T[] inputArray, int count) where T: struct
{
count = Math.Min(count, inputArray.Length);
int size = Marshal.SizeOf(typeof(T));
T[] result = new T[count];
Buffer.BlockCopy(inputArray, (inputArray.Length-count)*size, result, 0, count*size);
return result;
}
public static T[] TakeLastViaArrayCopy<T>(this T[] inputArray, int count) where T: struct
{
count = Math.Min(count, inputArray.Length);
T[] result = new T[count];
Array.Copy(inputArray, inputArray.Length-count, result, 0, count);
return result;
}
}
}
结果(像往常一样发布版本):
TakeLastViaArrayCopy took 00:00:00.3028503
TakeLastViaBlockCopy took 00:00:00.3052196
TakeLastViaArrayCopy took 00:00:00.2969425
TakeLastViaBlockCopy took 00:00:00.3000117
TakeLastViaArrayCopy took 00:00:00.2906120
TakeLastViaBlockCopy took 00:00:00.2987753
TakeLastViaArrayCopy took 00:00:00.2954674
TakeLastViaBlockCopy took 00:00:00.3005010
TakeLastViaArrayCopy took 00:00:00.2944490
TakeLastViaBlockCopy took 00:00:00.3006893
TakeLastViaArrayCopy took 00:00:00.3041998
TakeLastViaBlockCopy took 00:00:00.2920206
TakeLastViaArrayCopy took 00:00:00.3115137
TakeLastViaBlockCopy took 00:00:00.2996884
TakeLastViaArrayCopy took 00:00:00.2906820
TakeLastViaBlockCopy took 00:00:00.2985933
Array.Copy()
更简单易用,因此应该使用它。
new T[count]
后面跟着Array.Copy
?顺便说一下,如果有一个简短的程序可以演示Enumerable.Skip
/Enumerable.Take
的缓慢之处,那就太好了,这样就可以实际测试建议的替代方案,而不仅仅是猜测。 - user743382Take()
的调用是不必要的。如果你只使用myArray.Skip(myArray.Length - toTake)
,性能是否会有很大提升? - Lance U. MatthewsTake()
但仍然感觉很慢。 - J4N