Abrufen eines Sub-Arrays aus einem vorhandenen Array

335

Ich habe ein Array X von 10 Elementen. Ich möchte ein neues Array erstellen, das alle Elemente aus X enthält, die bei Index 3 beginnen und bei Index 7 enden. Natürlich kann ich leicht eine Schleife schreiben, die dies für mich erledigt, aber ich möchte meinen Code so sauber wie möglich halten . Gibt es eine Methode in C #, die das für mich tun kann?

So etwas wie (Pseudocode):

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

Array.Copypasst nicht zu meinen Bedürfnissen . Ich brauche die Elemente im neuen Array, um Klone zu sein. Array.copyist nur ein C-Style- memcpyÄquivalent, es ist nicht das, wonach ich suche.

user88637
quelle
7
@Kirtan - dieser "Dup" möchte speziell IEnumerable <T> - was anders ist und andere optimale Lösungen hat; IMO
Marc Gravell
Die beiden Zeilen, die benötigt werden, um das neue Array zu deklarieren und .Copy () aufzurufen, sind also kein "sauberer Code"?
Ed S.
2
@ Ed Swangren - nicht, wenn Sie es mitten in einem verketteten Ausdruck tun müssen, nein ;-p
Marc Gravell
2
ShaggyUks Antwort ist wahrscheinlich die richtige: stackoverflow.com/questions/943635/…
Dykam

Antworten:

469

Sie können es als Erweiterungsmethode hinzufügen:

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}
}

Aktualisieren Sie das erneute Klonen (was in der ursprünglichen Frage nicht offensichtlich war). Wenn Sie wirklich einen tiefen Klon wollen; etwas wie:

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

Dies erfordert jedoch, dass die Objekte serialisierbar ( [Serializable]oder ISerializable) sind. - Sie könnten für andere Serializer gegebenenfalls leicht ersetzen XmlSerializer, DataContractSerializer, protobuf-net etc.

Beachten Sie, dass Deep Clone ohne Serialisierung schwierig ist. Insbesondere ICloneableist es in den meisten Fällen schwer zu vertrauen.

Marc Gravell
quelle
1
(Offensichtlich ist die Verwendung eines Endindex anstelle einer Länge eine einfache Änderung. Ich habe "wie sie ist" gepostet, da dies die "typischere" Verwendung ist.)
Marc Gravell
1
Dann ... hart; Das geht nicht ... Sie müssten wahrscheinlich die Serialisierung verwenden, um etwas Ähnliches zu erreichen
Marc Gravell
1
Siehe meine Antwort für einige Alternativen und einen Link zu mehreren Implementierungen. Der Teil, in dem es darum geht, es mit einem Sub-Array zu tun, ist wirklich ziemlich trivial. Was Sie wirklich wollen, ist das Klonen und das ist eine komplexe und etwas offene Frage, die ganz von Ihren Erwartungen abhängt, was "korrektes" Verhalten sein sollte .
ShuggyCoUk
2
Das ist nett. Und es ist besonders gut darauf hinzuweisen, dass ICloneable unzuverlässig ist, denn oh, ist es jemals.
Marcus Griep
1
Vielen Dank, dass Sie die Probleme beim Deep Cloning in C # hervorgehoben haben. Es ist wirklich eine Schande, denn tiefes Kopieren ist eine grundlegende Operation .
Dimitri C.
316

Sie können verwenden, Array.Copy(...)um in das neue Array zu kopieren, nachdem Sie es erstellt haben, aber ich glaube nicht, dass es eine Methode gibt, die das neue Array erstellt und eine Reihe von Elementen kopiert.

Wenn Sie mit .NET 3.5 Sie können LINQ verwenden:

var newArray = array.Skip(3).Take(5).ToArray();

aber das wird etwas weniger effizient sein.

In dieser Antwort auf eine ähnliche Frage finden Sie Optionen für spezifischere Situationen.

Jon Skeet
quelle
+1 Ich mag diese Variante auch. Jon, kannst du näher erläutern, warum dies als weniger effizient angesehen wird?
Ian Roke
@ Jon: Um die Frage zu beantworten, wäre das nicht "Take (5)"? @ Ian: Der Array.Copy-Ansatz beinhaltet keinen Enumerator und wird höchstwahrscheinlich eine reine Memkopie sein ...
Marc Gravell
@ Marc: Ja in der Tat. Zu viele Fragen überfliegen :)
Jon Skeet
11
@Ian: Der LINQ-Ansatz führt zwei Indirektionsebenen ein (die Iteratoren), muss Elemente explizit überspringen und weiß nicht, wie groß das endgültige Array im Voraus sein wird. Betrachten Sie die zweite Hälfte eines Arrays mit zwei Millionen Elementen: Ein einfacher Ansatz zum Erstellen eines Zielarrays zum Kopieren kopiert nur den erforderlichen Block, ohne die anderen Elemente zu berühren, und zwar auf einmal. Der LINQ-Ansatz durchläuft das Array bis zum Startpunkt, nimmt dann Werte auf, baut einen Puffer auf (erhöht die Puffergröße und kopiert regelmäßig). Viel weniger effizient.
Jon Skeet
Wenn 5 der EndIndexm ist, lautet die richtige Frage array.Skip (3) .Take (5-3 + 1) .ToArray (); dh. array.Skip (StartIndex) .Take (EndIndex-StartIndex + 1) .ToArray ();
Klaus78
73

Haben Sie darüber nachgedacht, zu verwenden ArraySegment?

http://msdn.microsoft.com/en-us/library/1hsbd92d.aspx

Alex Black
quelle
1
Es macht wahrscheinlich das, was Sie wollen, aber es unterstützt weder die Standard-Array-Syntax noch IEnumerable, so dass es nicht besonders sauber ist.
Alex Black
5
Dies erfordert mehr Zustimmung. In meiner eigenen Erfahrung ist das Kopieren von ArraySegments auch etwas schneller (schließlich verwende ich Arrays für geschwindigkeitskritische
Dinge
5
@AlexBlack Es sieht aus wie ab .NET 4.5 , es implementiert IEnumerable<T>und eine Vielzahl anderer nützlicher Schnittstellen.
Pswg
1
Wie würden Sie ArraySegmentdie ursprüngliche Frage beantworten?
Craig McQueen
2
@CraigMcQueen - Versuchen Sie den folgenden einzeiligen Ansatz:IList<T> newArray = (IList<T>)new ArraySegment<T>(oldArray, beginIndex, endIndex);
skia.heliou
36

Ich sehe, Sie möchten klonen und nicht nur Referenzen kopieren. In diesem Fall können Sie .SelectArray-Mitglieder auf ihre Klone projizieren. Wenn Ihre Elemente beispielsweise implementiert sind, können IClonableSie Folgendes tun:

var newArray = array.Skip(3).Take(5).Select(eachElement => eachElement.Clone()).ToArray();

Hinweis: Für diese Lösung ist .NET Framework 3.5 erforderlich.

zvolkov
quelle
Das ist eleganter.
smwikipedia
Genau das habe ich gesucht. Dies funktioniert für alle IEnumerable. Ich kann eine bekommen IEnumerable, IList, IArrayusw ... mit minimalem Aufwand, Inline , wenn ich muss. Wenn ich die tiefe Kopie nicht brauche, entferne ich einfach die Select. Fallenlassen Skipoder Takeerlaubt mir, die Reichweite zu kontrollieren. Alternativ kann ich es mit SkipWhileund / oder verwechseln TakeWhile.
Mike
33

Der folgende Code macht es in einer Zeile:

// 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();
Volker
quelle
Einzelne Linie und keine Notwendigkeit, Linq hinzuzufügen. Es ist mein bevorzugter Weg.
Dimitris
Trotzdem klont es die Quelle nicht ... aber es ist trotzdem ein guter Ansatz
IG Pascual
1
Es sollte die Quelle klonen, da ToArray: (1) ein neues Array erstellt und (2) Array.Copy ausführt. Am Ende sind Source und Slice zwei separate Objekte. Der Ansatz ist korrekt, ich bevorzuge jedoch Array.Copy: referencesource.microsoft.com/#mscorlib/system/collections/…
Krauss
13

In C # 8 haben sie eine neue eingeführt Rangeund IndexArt

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 }
Prasanth Louis
quelle
12
string[] arr = { "Parrot" , "Snake" ,"Rabbit" , "Dog" , "cat" };

arr = arr.ToList().GetRange(0, arr.Length -1).ToArray();
user3698437
quelle
8

Aufbauend auf Marc's Antwort, aber Hinzufügen des gewünschten Klonverhaltens

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

Und wenn die Implementierung von ICloneable zu viel wie harte Arbeit ist, reflektieren Sie sie mithilfe der kopierbaren Bibliothek von Håvard Stranden , um das erforderliche schwere Heben zu erledigen.

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

Beachten Sie, dass die OX.Copyable-Implementierung mit folgenden Funktionen funktioniert:

Damit die automatisierte Kopie funktioniert, muss beispielsweise eine der folgenden Anweisungen gelten:

  • Sein Typ muss einen parameterlosen Konstruktor haben, oder
  • Es muss kopierbar sein, oder
  • Für seinen Typ muss ein IInstanceProvider registriert sein.

Dies sollte also fast jede Situation abdecken, die Sie haben. Wenn Sie Objekte klonen, in denen das Subdiagramm Dinge wie Datenbankverbindungen oder Datei- / Stream-Handles enthält, haben Sie offensichtlich Probleme, aber das gilt für jede verallgemeinerte tiefe Kopie.

Wenn Sie stattdessen einen anderen Deep-Copy-Ansatz verwenden möchten, werden in diesem Artikel mehrere andere aufgelistet. Ich würde daher empfehlen, nicht zu versuchen, einen eigenen zu schreiben.

ShuggyCoUk
quelle
Der erste ist wahrscheinlich die gewünschte Lösung, da er um das Klonen bittet. Beachten Sie, dass Sie mit der Copy-Methode wahrscheinlich nicht einmal nach null suchen müssen, da es sich um eine Erweiterungsmethode handelt, wenn die Methode selbst dies bereits tut. Einen Versuch wert.
Dykam
Ja, ich habe die Nullprüfung notiert, wollte aber das OP nicht verwirren, falls er die Quelle nicht gelesen hat.
ShuggyCoUk
2
Nur eine Randnotiz: Für die neueste Version von Copyable on GitHub müssen Objekte keinen parameterlosen Konstruktor haben. :) Siehe github.com/havard/copyable
Håvard S
8

Sie können dies ziemlich einfach tun;

    object[] foo = new object[10];
    object[] bar = new object[7];   
    Array.Copy(foo, 3, bar, 0, 7);  
RandomNickName42
quelle
Nein, der Balken ist immer noch null. Array.Copy erstellt auf magische Weise kein neues Array, zumal der Balken nicht mit ref oder out übergeben wird.
Zr40
2
oh ya hey, dein Recht, ich habe das in Eile getan, aber hey, vielleicht ist konstruktive Kritik für alle so viel nützlicher, wenn deine Schreibkritik korrigiert werden soll. Also machen Sie vor dieser array.copy ein "bar = new object [7];"
RandomNickName42
4

Ich denke, dass der Code, den Sie suchen, ist:

Array.Copy(oldArray, 0, newArray, BeginIndex, EndIndex - BeginIndex)

Sean
quelle
Ich glaube, ich habe hier ein paar gute Freunde gefunden ... die gleiche Antwort wie du;) und ich wurde reichlich abgewählt !! hah !! Wie auch immer, gute Zeiten, gute Zeiten.
RandomNickName42
3

Alternativ zum Kopieren der Daten können Sie einen Wrapper erstellen, mit dem Sie auf einen Teil des ursprünglichen Arrays zugreifen können, als wäre es eine Kopie des Teils des Arrays. Der Vorteil ist, dass Sie keine weitere Kopie der Daten im Speicher erhalten und der Nachteil ein leichter Aufwand beim Zugriff auf die Daten ist.

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

}

Verwendungszweck:

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
Guffa
quelle
@ Robert: Nein, das ist es nicht. Versuchen Sie stattdessen, ein ArraySegment zu verwenden, und Sie sehen, dass Sie weder über den Index auf die Elemente zugreifen noch durch die Elemente iterieren können.
Guffa
2

Array.ConstrainedCopy funktioniert.

public static void ConstrainedCopy (
    Array sourceArray,
    int sourceIndex,
    Array destinationArray,
    int destinationIndex,
    int length
)
Crauscher
quelle
2
Das kopiert nur die Daten; Das neue Array usw. wird nicht erstellt. und wenn das Array neu ist, könnten wir Array.Copy verwenden, das effizienter ist (keine zusätzlichen Überprüfungen / Rollbacks erforderlich).
Marc Gravell
Das ist richtig, aber das Erstellen eines neuen Arrays ist nur eine Codezeile und es ist keine neue Methode erforderlich. Ich bin damit einverstanden, dass Array.Copy auch funktioniert.
Crauscher
1

Es gibt keine einzige Methode, die das tut, was Sie wollen. Sie müssen eine Klonmethode für die Klasse in Ihrem Array verfügbar machen. Wenn dann LINQ eine Option ist:

Foo[] newArray = oldArray.Skip(3).Take(5).Select(item => item.Clone()).ToArray();

class Foo
{
    public Foo Clone()
    {
        return (Foo)MemberwiseClone();
    }
}
Thorarin
quelle
1

Wie wäre es mit Array.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);

Unten ist mein ursprünglicher Beitrag. Es wird nicht funktionieren

Sie könnten Array.CopyTo verwenden :

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
Mike
quelle
1

Wie wäre es damit:

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;

}

Sie müssen dann die ICloneable-Schnittstelle für alle Klassen implementieren, für die Sie diese verwenden müssen, aber das sollte es tun.

RCIX
quelle
1

Ich bin mir nicht sicher, wie tief es wirklich ist, aber:

MyArray.ToList<TSource>().GetRange(beginningIndex, endIndex).ToArray()

Es ist ein bisschen Overhead, aber es könnte eine unnötige Methode ausschließen.

SCNerd
quelle
1

C # 8 hat eine Funktion namens Range bereitgestellt, mit der der Subarry vom Anfangs- bis zum Endindex abgerufen werden kann. Sie können es so verwenden.

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

Was das Klonen angeht, glaube ich nicht, dass die Serialisierung Ihre Konstruktoren aufruft. Dies kann Klasseninvarianten brechen, wenn Sie interessante Dinge im Ctor tun.

Es scheint, dass die sicherere Wette virtuelle Klonmethoden sind, die Kopierkonstruktoren aufrufen.

protected MyDerivedClass(MyDerivedClass myClass) 
{
  ...
}

public override MyBaseClass Clone()
{
  return new MyDerivedClass(this);
}
Hans Malherbe
quelle
Ob die Serialisierung Ihre Konstruktoren aufruft, hängt vom jeweiligen Serializer ab. Einige tun es, andere nicht. Aber diejenigen, die normalerweise keine Rückrufunterstützung bieten, damit Sie alle erforderlichen Korrekturen vornehmen können.
Marc Gravell
Dies unterstreicht einen weiteren Reibungspunkt der Serialisierung: Sie müssen Standardkonstruktoren bereitstellen.
Hans Malherbe
0

Das Klonen von Elementen in einem Array ist nicht universell möglich. Möchten Sie ein tiefes Klonen oder eine einfache Kopie aller Mitglieder?

Gehen wir zum "Best Effort" -Ansatz über: Klonen von Objekten mithilfe der ICloneable-Schnittstelle oder der binären Serialisierung:

public static class ArrayExtensions
{
  public static T[] SubArray<T>(this T[] array, int index, int length)
  {
    T[] result = new T[length];

    for (int i=index;i<length+index && i<array.Length;i++)
    {
       if (array[i] is ICloneable)
          result[i-index] = (T) ((ICloneable)array[i]).Clone();
       else
          result[i-index] = (T) CloneObject(array[i]);
    }

    return result;
  }

  private static object CloneObject(object obj)
  {
    BinaryFormatter formatter = new BinaryFormatter();

    using (MemoryStream stream = new MemoryStream())
    {
      formatter.Serialize(stream, obj);

      stream.Seek(0,SeekOrigin.Begin);

      return formatter.Deserialize(stream);
    }
  }
}

Dies ist keine perfekte Lösung, da es einfach keine gibt, die für jeden Objekttyp geeignet ist.

Philippe Leybaert
quelle
Sollte das nicht so etwas wie result [i-index] = (T) sein ...?
Donald Byrd
ja :) Und nicht nur das. Die Schleifengrenze ist falsch. Ich werde es reparieren. Vielen Dank!
Philippe Leybaert
0

Sie können an einem Kurs von Microsoft teilnehmen:

internal class Set<TElement>
{
    private int[] _buckets;
    private Slot[] _slots;
    private int _count;
    private int _freeList;
    private readonly IEqualityComparer<TElement> _comparer;

    public Set()
        : this(null)
    {
    }

    public Set(IEqualityComparer<TElement> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<TElement>.Default;
        _comparer = comparer;
        _buckets = new int[7];
        _slots = new Slot[7];
        _freeList = -1;
    }

    public bool Add(TElement value)
    {
        return !Find(value, true);
    }

    public bool Contains(TElement value)
    {
        return Find(value, false);
    }

    public bool Remove(TElement value)
    {
        var hashCode = InternalGetHashCode(value);
        var index1 = hashCode % _buckets.Length;
        var index2 = -1;
        for (var index3 = _buckets[index1] - 1; index3 >= 0; index3 = _slots[index3].Next)
        {
            if (_slots[index3].HashCode == hashCode && _comparer.Equals(_slots[index3].Value, value))
            {
                if (index2 < 0)
                    _buckets[index1] = _slots[index3].Next + 1;
                else
                    _slots[index2].Next = _slots[index3].Next;
                _slots[index3].HashCode = -1;
                _slots[index3].Value = default(TElement);
                _slots[index3].Next = _freeList;
                _freeList = index3;
                return true;
            }
            index2 = index3;
        }
        return false;
    }

    private bool Find(TElement value, bool add)
    {
        var hashCode = InternalGetHashCode(value);
        for (var index = _buckets[hashCode % _buckets.Length] - 1; index >= 0; index = _slots[index].Next)
        {
            if (_slots[index].HashCode == hashCode && _comparer.Equals(_slots[index].Value, value))
                return true;
        }
        if (add)
        {
            int index1;
            if (_freeList >= 0)
            {
                index1 = _freeList;
                _freeList = _slots[index1].Next;
            }
            else
            {
                if (_count == _slots.Length)
                    Resize();
                index1 = _count;
                ++_count;
            }
            int index2 = hashCode % _buckets.Length;
            _slots[index1].HashCode = hashCode;
            _slots[index1].Value = value;
            _slots[index1].Next = _buckets[index2] - 1;
            _buckets[index2] = index1 + 1;
        }
        return false;
    }

    private void Resize()
    {
        var length = checked(_count * 2 + 1);
        var numArray = new int[length];
        var slotArray = new Slot[length];
        Array.Copy(_slots, 0, slotArray, 0, _count);
        for (var index1 = 0; index1 < _count; ++index1)
        {
            int index2 = slotArray[index1].HashCode % length;
            slotArray[index1].Next = numArray[index2] - 1;
            numArray[index2] = index1 + 1;
        }
        _buckets = numArray;
        _slots = slotArray;
    }

    internal int InternalGetHashCode(TElement value)
    {
        if (value != null)
            return _comparer.GetHashCode(value) & int.MaxValue;
        return 0;
    }

    internal struct Slot
    {
        internal int HashCode;
        internal TElement Value;
        internal int Next;
    }
}

und dann

public static T[] GetSub<T>(this T[] first, T[] second)
    {
        var items = IntersectIteratorWithIndex(first, second);
        if (!items.Any()) return new T[] { };


        var index = items.First().Item2;
        var length = first.Count() - index;
        var subArray = new T[length];
        Array.Copy(first, index, subArray, 0, length);
        return subArray;
    }

    private static IEnumerable<Tuple<T, Int32>> IntersectIteratorWithIndex<T>(IEnumerable<T> first, IEnumerable<T> second)
    {
        var firstList = first.ToList();
        var set = new Set<T>();
        foreach (var i in second)
            set.Add(i);
        foreach (var i in firstList)
        {
            if (set.Remove(i))
                yield return new Tuple<T, Int32>(i, firstList.IndexOf(i));
        }
    }
Smagin Alexey
quelle
0

Ich fand, dass dies der optimale Weg ist, dies zu tun:

private void GetSubArrayThroughArraySegment() {
  int[] array = { 10, 20, 30 };
  ArraySegment<int> segment = new ArraySegment<int>(array,  1, 2);
  Console.WriteLine("-- Array --");
  int[] original = segment.Array;
  foreach (int value in original)
  {
    Console.WriteLine(value);
  }
  Console.WriteLine("-- Offset --");
  Console.WriteLine(segment.Offset);
  Console.WriteLine("-- Count --");
  Console.WriteLine(segment.Count);

  Console.WriteLine("-- Range --");
  for (int i = segment.Offset; i <= segment.Count; i++)
  {
    Console.WriteLine(segment.Array[i]);
  }
}

Ich hoffe es hilft!

OscarMas
quelle
0

Erweiterungsmethode verwenden:

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

und du kannst es benutzen

var NewArray = OldArray.Slice(3,7);
Erwin Draconis
quelle
0

Code aus der 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;
}


Ezequiel Maygua
quelle
0

Es erfüllt nicht Ihre Klonanforderungen, aber es scheint einfacher als viele Antworten zu sein:

Array NewArray = new ArraySegment(oldArray,BeginIndex , int Count).ToArray();
Mr. Boy
quelle
-1
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();
        }
Binay Rana
quelle