How do I clone a range of array elements to a new array?

前端 未结 25 976
北海茫月
北海茫月 2020-11-22 16:07

I have an array X of 10 elements. I would like to create a new array containing all the elements from X that begin at index 3 and ends in index 7. Sure I can easily write a

相关标签:
25条回答
  • 2020-11-22 16:40

    You can do this fairly easially;

        object[] foo = new object[10];
        object[] bar = new object[7];   
        Array.Copy(foo, 3, bar, 0, 7);  
    
    0 讨论(0)
  • 2020-11-22 16:40

    In C# 8.0, you can now do many fancier works including reverse indices and ranges like in Python, such as:

    int[] list = {1, 2, 3, 4, 5, 6};
    var list2 = list[2..5].Clone() as int[]; // 3, 4, 5
    var list3 = list[..5].Clone() as int[];  // 1, 2, 3, 4, 5
    var list4 = list[^4..^0].Clone() as int[];  // reverse index
    
    0 讨论(0)
  • 2020-11-22 16:40

    Code from the System.Private.CoreLib.dll:

    public static T[] GetSubArray<T>(T[] array, Range range)
    {
        if (array == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
        }
        (int Offset, int Length) offsetAndLength = range.GetOffsetAndLength(array.Length);
        int item = offsetAndLength.Offset;
        int item2 = offsetAndLength.Length;
        if (default(T) != null || typeof(T[]) == array.GetType())
        {
            if (item2 == 0)
            {
                return Array.Empty<T>();
            }
            T[] array2 = new T[item2];
            Buffer.Memmove(ref Unsafe.As<byte, T>(ref array2.GetRawSzArrayData()), ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), item), (uint)item2);
            return array2;
        }
        T[] array3 = (T[])Array.CreateInstance(array.GetType().GetElementType(), item2);
        Array.Copy(array, item, array3, 0, item2);
        return array3;
    }
    


    0 讨论(0)
  • 2020-11-22 16:43

    Building on Marc's answer but adding the desired cloning behaviour

    public static T[] CloneSubArray<T>(this T[] data, int index, int length)
        where T : ICloneable
    {
        T[] result = new T[length];
        for (int i = 0; i < length; i++)
        { 
            var original = data[index + i];
            if (original != null)
                result[i] = (T)original.Clone();            
        return result;
    }
    

    And if implementing ICloneable is too much like hard work a reflective one using Håvard Stranden’s Copyable library to do the heavy lifting required.

    using OX.Copyable;
    
    public static T[] DeepCopySubArray<T>(
        this T[] data, int index, int length)
    {
        T[] result = new T[length];
        for (int i = 0; i < length; i++)
        { 
            var original = data[index + i];
            if (original != null)
                result[i] = (T)original.Copy();            
        return result;
    }
    

    Note that the OX.Copyable implementation works with any of:

    For the automated copy to work, though, one of the following statements must hold for instance:

    • Its type must have a parameterless constructor, or
    • It must be a Copyable, or
    • It must have an IInstanceProvider registered for its type.

    So this should cover almost any situation you have. If you are cloning objects where the sub graph contains things like db connections or file/stream handles you obviously have issues but that it true for any generalized deep copy.

    If you want to use some other deep copy approach instead this article lists several others so I would suggest not trying to write your own.

    0 讨论(0)
  • 2020-11-22 16:45

    How about this:

    public T[] CloneCopy(T[] array, int startIndex, int endIndex) where T : ICloneable
    {
        T[] retArray = new T[endIndex - startIndex];
        for (int i = startIndex; i < endIndex; i++)
        {
            array[i - startIndex] = array[i].Clone();
        }
        return retArray;
    
    }
    

    You then need to implement the ICloneable interface on all of the classes you need to use this on but that should do it.

    0 讨论(0)
  • 2020-11-22 16:47

    It does not meet your cloning requirement, but it seems simpler than many answers to do:

    Array NewArray = new ArraySegment(oldArray,BeginIndex , int Count).ToArray();
    
    0 讨论(0)
提交回复
热议问题