如何通过C#快捷的从一个数组中提取出子数组?

咨询区

  • user88637

我有一个包含10个元素的 数组X,我希望能从这个新数组 X 中提取出指定一段作为新数组,比如序号 3-7 之间,当然这种需求,我可以很容易的写一个循环逐个提取,但这种办法比较生硬,有没有简单粗暴的做法,或者说 C# 中是否有现成的方法做这个?

我想象中的伪代码大概是这样的。.

Array NewArray = oldArray.createNewArrayFromRange(int BeginIndex , int EndIndex)

回答区

  • Prasanth Louis

在 C#8 中引入了 Range 和 Index 特性,你完全可以像下面这样写。

int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
var slice = a[i1..i2]; // { 3, 4, 5 }

更多资料可参考:

  1. https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-0#ranges-and-indices

  2. https://devblogs.microsoft.com/dotnet/building-c-8-0/

  • Mike

可以考虑使用 Array.ConstrainedCopy() 方法,它可以帮你提取子集合,签名如下:

        //
        // Summary:
        //     Copies a range of elements from an System.Array starting at the specified source
        //     index and pastes them to another System.Array starting at the specified destination
        //     index. Guarantees that all changes are undone if the copy does not succeed completely.
        //
        public static void ConstrainedCopy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
        {
        }

然后可以参考下面的例子:

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
Array.ConstrainedCopy(ArrayOne, 3, ArrayTwo, 0, 7-3);
  • Erwin Draconis

这个其实很简单,自己封装一个扩展方法就可以了。

    public static T[] Slice<T>(this T[] source, int start, int end)
    {
        // Handles negative ends.
        if (end < 0)
        {
            end = source.Length + end;
        }
        int len = end - start;

        // Return new array.
        T[] res = new T[len];
        for (int i = 0; i < len; i++)
        {
            res[i] = source[i + start];
        }
        return res;
    }

然后就可以这样使用。

var NewArray = OldArray.Slice(3,7);

点评区

各位大佬提供的方法都很不错,尤其是 C#8 中的新特性,特别方便实用。