我有一个包含10个元素的数组X。我想创建一个新数组,包含X中从索引3开始并在索引7结束的所有元素。当然,我可以很容易地写一个循环,将它为我,但我想保持我的代码尽可能干净。c#中有一个方法可以帮我做这个吗?

类似(伪代码):

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

数组中。拷贝不符合我的需要。我需要在新数组中的项目是克隆。数组中。copy只是一个c风格的memcpy等效,这不是我要找的。


当前回答

public   static   T[]   SubArray<T>(T[] data, int index, int length)
        {
            List<T> retVal = new List<T>();
            if (data == null || data.Length == 0)
                return retVal.ToArray();
            bool startRead = false;
            int count = 0;
            for (int i = 0; i < data.Length; i++)
            {
                if (i == index && !startRead)
                    startRead = true;
                if (startRead)
                {

                    retVal.Add(data[i]);
                    count++;

                    if (count == length)
                        break;
                }
            }
            return retVal.ToArray();
        }

其他回答

下面的代码在一行中完成:

// Source array
string[] Source = new string[] { "A", "B", "C", "D" };
// Extracting a slice into another array
string[] Slice = new List<string>(Source).GetRange(2, 2).ToArray();

数组中。ConstrainedCopy将工作。

public static void ConstrainedCopy (
    Array sourceArray,
    int sourceIndex,
    Array destinationArray,
    int destinationIndex,
    int length
)

作为复制数据的替代方法,您可以制作一个包装器,使您可以访问原始数组的一部分,就像它是该数组部分的副本一样。这样做的优点是不会在内存中获得数据的另一个副本,缺点是在访问数据时产生轻微的开销。

public class SubArray<T> : IEnumerable<T> {

   private T[] _original;
   private int _start;

   public SubArray(T[] original, int start, int len) {
      _original = original;
      _start = start;
      Length = len;
   }

   public T this[int index] {
      get {
         if (index < 0 || index >= Length) throw new IndexOutOfRangeException();
         return _original[_start + index];
      }
   }

   public int Length { get; private set; }

   public IEnumerator<T> GetEnumerator() {
      for (int i = 0; i < Length; i++) {
        yield return _original[_start + i];
      }
   }

   IEnumerator IEnumerable.GetEnumerator() {
      return GetEnumerator();
   }

}

用法:

int[] original = { 1, 2, 3, 4, 5 };
SubArray<int> copy = new SubArray<int>(original, 2, 2);

Console.WriteLine(copy.Length); // shows: 2
Console.WriteLine(copy[0]); // shows: 3
foreach (int i in copy) Console.WriteLine(i); // shows 3 and 4

那么使用数组呢?ConstrainedCopy:

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);

以下是我的原帖。这是行不通的

你可以使用数组。CopyTo:

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
ArrayOne.CopyTo(ArrayTwo,3); //starts copy at index=3 until it reaches end of
                             //either array

你可以添加它作为一个扩展方法:

public static T[] SubArray<T>(this T[] data, int index, int length)
{
    T[] result = new T[length];
    Array.Copy(data, index, result, 0, length);
    return result;
}
static void Main()
{
    int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int[] sub = data.SubArray(3, 4); // contains {3,4,5,6}
}

更新重新克隆(这在最初的问题中并不明显)。如果你真的想要一个深度克隆;喜欢的东西:

public static T[] SubArrayDeepClone<T>(this T[] data, int index, int length)
{
    T[] arrCopy = new T[length];
    Array.Copy(data, index, arrCopy, 0, length);
    using (MemoryStream ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, arrCopy);
        ms.Position = 0;
        return (T[])bf.Deserialize(ms);
    }
}

不过,这确实要求对象是可序列化的([serializable]或ISerializable)。您可以轻松地替换任何其他合适的序列化器——XmlSerializer、DataContractSerializer、protobuf-net等等。

注意,深度克隆在没有序列化的情况下是很棘手的;特别是,ICloneable在大多数情况下是很难信任的。