获取c#中数组的最后N个元素

本文关键字:元素 最后 数组 获取 | 更新日期: 2023-09-27 18:11:51

在c#中,返回数组最后N个元素的最有效方法是什么?

我正在处理成千上万个元素的数组,我更喜欢一个比基于LINQ的解决方案更有效的答案。

我也希望答案是单元测试,以避免超出一个错误。

获取c#中数组的最后N个元素

我可能会写:

public static T[] TakeLast<T>(this T[] source, int n)
{
        if(source == null)
            throw new ArgumentNullException(nameof(source));
        if(n > source.Length)
            throw new ArgumentOutOfRangeException(nameof(n), "Can't be bigger than the array");
        if(n < 0)
            throw new ArgumentOutOfRangeException(nameof(n), "Can't be negative");
        var target = new T[n]; 
        Array.Copy(source, source.Length - n, target, 0, n);
        return target;
}

如下:单元测试是针对NUnit

[TestFixture]
public static class MyTakeLastExtensions
{   
    /// <summary>
    /// Intent: Returns the last N elements from an array.
    /// </summary>
    public static T[] MyTakeLast<T>(this T[] source, int n)
    {
        if (source == null)
        {
            throw new Exception("Source cannot be null.");
        }
        if (n < 0)
        {
            throw new Exception("Index must be positive.");
        }
        if (source.Length < n)
        {
            return source;
        }
        var result = new T[n];
        int c = 0;
        for (int i = source.Length - n; i < source.Length; i++)
        {
            result[c] = source[i];
            c++;
        }
        return result;
    }
    [Test]
    public static void MyTakeLast_Test()
    {
        int[] a = new[] {0, 1, 2};
        {
            var b = a.MyTakeLast(2);
            Assert.True(b.Length == 2);
            Assert.True(b[0] == 1);
            Assert.True(b[1] == 2);
        }
        {
            var b = a.MyTakeLast(3);
            Assert.True(b.Length == 3);
            Assert.True(b[0] == 0);
            Assert.True(b[1] == 1);
            Assert.True(b[2] == 2);
        }
        {
            var b = a.MyTakeLast(4);
            Assert.True(b.Length == 3);
            Assert.True(b[0] == 0);
            Assert.True(b[1] == 1);
            Assert.True(b[2] == 2);
        }
        {
            var b = a.MyTakeLast(1);
            Assert.True(b.Length == 1);
            Assert.True(b[0] == 2);
        }
        {
            var b = a.MyTakeLast(0);
            Assert.True(b.Length == 0);
        }
        {               
            Assert.Throws<Exception>(() => a.MyTakeLast(-1));
        }
        {
            int[] b = null;
            Assert.Throws<Exception>(() => b.MyTakeLast(-1));
        }
    }
}