Wie verkette ich zwei Arrays in C #?

267
int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };

int[] z = // your answer here...

Debug.Assert(z.SequenceEqual(new int[] { 1, 2, 3, 4, 5 }));

Im Moment benutze ich

int[] z = x.Concat(y).ToArray();

Gibt es eine einfachere oder effizientere Methode?

hwiechers
quelle
8
Was meinst du mit "effizient"? Der Code ist so kurz wie er ist, also nehme ich an, Sie meinen effizient in Bezug auf CPU / RAM?
TToni
4
Nein, ein kurzer Blick mit Reflector zeigt, dass es einen Double-When-Full-Puffer verwendet
erikkallen
Sei dir nur klar, dass z vom Typ int [] sein muss.
Hwiechers
4
Ich bin nicht wirklich besorgt um Effizienz. (Ich habe gesagt, einfacher oder effizienter.) Ich stellte die Frage, um zu überprüfen, wie andere Leute mit dieser gemeinsamen Aufgabe umgehen.
Hwiechers

Antworten:

331
var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);
Zed
quelle
8
@manthrax -> Zu seiner Verteidigung bevorzugt C # Listen, die viel leistungsfähiger sind als Arrays. Es scheint, dass der einzige funktionale Zweck für die Verwendung von Arrays Interop-Aufrufe (nicht verwaltetes C ++) sind.
Levi Fuller
@LeviFuller Ein weiterer Ort, an dem C # ein Array verwendet, sind paramsParameter mit variabler Anzahl .
ChrisW
1
@LeviFuller - Es ist seltsam, dass viele Systemroutinen Arrays anstelle von Listen zurückgeben. zB System.IO.Directory.GetFiles()gibt ein Array von Strings zurück.
Orion Elenzil
4
Das ist nicht seltsam. Ein Array ist unveränderlich, eine Liste nicht. Auch eine Liste verwendet mehr Speicher als ein Array, es sei denn, TrimExcess wird aufgerufen (was in ToList nicht vorkommt)
CSharpie
1
Außerdem ist das Array beim Zugriff auf Daten schneller als die Liste, da die Liste das Array nur einschließt und Overhead für den Aufruf des Indexers hat.
C0DEF52
84

Versuche dies:

List<int> list = new List<int>();
list.AddRange(x);
list.AddRange(y);
int[] z = list.ToArray();
Adriaan Stander
quelle
5
Oder sogarList<int> list = new List<int>(x);
Matthew Scharley
7
Wie ist das effizienter als x.Concat (y)? Es funktioniert und alles, ich frage mich nur, ob es etwas gibt, das es besser macht?
Mike Two
7
Vielleicht möchten Sie die erste Zeile erstellen. List <int> list = new List <int> (x.Length + y.Length); Um die Größenänderung zu vermeiden, die beim Aufrufen von AddRange
Mike Two
5
@ Mathew Scharley. Die Frage ist nach einer effizienteren Lösung. Ich weiß, dass der Titel so klingt, als würde jede alte Kombination funktionieren, aber die ganze Frage geht darüber hinaus. Wenn ich einige der Antworten lese, habe ich das Gefühl, dass einige Leute den Titel beantworten. Daher dachte ich, dass diese Antwort wahrscheinlich die Effizienz erwähnen sollte, wenn sie die positiven Stimmen verdient, da dies der Punkt der Frage zu sein schien.
Mike Two
2
Es stellt sich heraus, dass der AddRange tatsächlich ein ziemlich teurer Prozess ist, daher sollte die erste Antwort auf diesem Board der bevorzugte Ansatz sein: dotnetperls.com/insertrange
Liam
49

Sie könnten eine Erweiterungsmethode schreiben:

public static T[] Concat<T>(this T[] x, T[] y)
{
    if (x == null) throw new ArgumentNullException("x");
    if (y == null) throw new ArgumentNullException("y");
    int oldLen = x.Length;
    Array.Resize<T>(ref x, x.Length + y.Length);
    Array.Copy(y, 0, x, oldLen, y.Length);
    return x;
}

Dann:

int[] x = {1,2,3}, y = {4,5};
int[] z = x.Concat(y); // {1,2,3,4,5}
Marc Gravell
quelle
1
Gibt es nicht bereits eine Erweiterungsmethode, die auf jedem IEnumerable funktioniert?
Mike Two
2
Ja, und das würde ich in den meisten Fällen gerne nutzen. Aber sie haben viele Gemeinkosten. Es hängt davon ab, ob; In 98% der Fälle sind die Gemeinkosten in Ordnung. Wenn Sie jedoch bei 2% sind, ist eine direkte Memcopy- / Array-Arbeit praktisch.
Marc Gravell
1
@nawfal, wie geht es Copyschneller als CopyTo? Möchtest du das näher erläutern?
Skrebbel
1
@skrebbel meins war ein ungenauer Kommentar. Ich habe damals einige Tests durchgeführt und Copy schneller gefunden. Aber jetzt scheinen sie einfach gleich zu sein. Was ich damals vielleicht gefunden habe, könnte sein, dass der Ansatz von Marc insgesamt effizienter ist, da er dieselbe Instanz zurückgibt, während er in Zeds Ansatz ein neues Array erstellt. Entschuldigung :)
Nawfal
1
@ Shimmy würde es nicht. Innerhalb dieser Methode ist x nur eine lokale Variable. Wenn Sie x als Referenz an die Größenänderungsmethode übergeben, wird ein neues Array erstellt und (die lokale Variable) x wird so geändert, dass es darauf verweist. Oder um es neu zu formulieren: x, das an die Größenänderung übergeben wird, und x innerhalb der Erweiterungsmethode ist dieselbe Variable, aber x wird nicht als Referenz an die Erweiterungsmethode übergeben, sodass x eine andere Variable ist als die Variable in dem Bereich, aus dem diese Erweiterung aufgerufen wurde .
AnorZaken
40

Ich habe mich für eine allgemeinere Lösung entschieden, mit der eine beliebige Menge eindimensionaler Arrays desselben Typs verkettet werden kann. (Ich habe 3+ gleichzeitig verkettet.)

Meine Funktion:

    public static T[] ConcatArrays<T>(params T[][] list)
    {
        var result = new T[list.Sum(a => a.Length)];
        int offset = 0;
        for (int x = 0; x < list.Length; x++)
        {
            list[x].CopyTo(result, offset);
            offset += list[x].Length;
        }
        return result;
    }

Und Verwendung:

        int[] a = new int[] { 1, 2, 3 };
        int[] b = new int[] { 4, 5, 6 };
        int[] c = new int[] { 7, 8 };
        var y = ConcatArrays(a, b, c); //Results in int[] {1,2,3,4,5,6,7,8}
deepee1
quelle
Gute Funktion, danke! Geändert params T[][], this T[][]um es zu einer Erweiterung zu machen.
Mark
Hallo Leute, diese Funktion sieht so aus, wie ich gesucht habe, aber eine Idee, wie ich das erreichen kann? Link @ Mark
George B
31

Das ist es:

using System.Linq;

int[] array1 = { 1, 3, 5 };
int[] array2 = { 0, 2, 4 };

// Concatenate array1 and array2.
var result1 = array1.Concat(array2);
Roland
quelle
4
Sie meinen, int[] result = array1.ToList().Concat(array2.ToList()).toArray();Sie können Concat nicht direkt auf Arrays anwenden, glaube ich
Michail Michailidis
4
Diese Lösung - z = x.Concat (y) - wurde in der ursprünglichen Frage oben erwähnt.
Jon Schneider
1
Dies ist, was ohne dietoArray() Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to 'string[]'. An explicit conversion exists (are you missing a cast?)
Tibor Udvari
2
Dies ist keine direkte Antwort. OP gefragt int[] result = ?, Sie verstecken das Problem Ihrer Antwort hinter Ihrem, vardass Ihr Ergebnis sein wird IEnumerable<int>, nicht int[]. (Einer der Gründe, warum ich varbei Methodenrückgaben nicht mag )
David S.
2
Diese Methode wird in der Frage verwendet, sodass diese Antwort keine neuen Informationen enthält. Ohne den .ToArray()Aufruf gibt dieser Code kein tatsächliches Array zurück, sodass es sich auch um eine falsche Antwort handelt.
Mani Gandham
10

Sie können den ToArray () -Aufruf am Ende abbrechen. Gibt es einen Grund, warum es nach dem Aufruf von Concat ein Array sein muss?

Durch Aufrufen von Concat wird ein Iterator über beide Arrays erstellt. Es wird kein neues Array erstellt, sodass Sie nicht mehr Speicher für ein neues Array verwendet haben. Wenn Sie ToArray aufrufen, erstellen Sie tatsächlich ein neues Array und belegen den Speicher für das neue Array.

Wenn Sie also nur einfach über beide iterieren müssen, rufen Sie einfach Concat an.

Mike Zwei
quelle
8

Ich weiß, dass das OP nur leicht neugierig auf die Leistung war. Diese größeren Arrays erhalten möglicherweise ein anderes Ergebnis (siehe @kurdishTree). Und dass es normalerweise keine Rolle spielt (@ jordan.peoples). Trotzdem war ich neugierig und verlor deshalb den Verstand (wie @TigerShark erklärte) .... Ich meine, ich habe einen einfachen Test geschrieben, der auf der ursprünglichen Frage basiert .... und allen Antworten ....

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace concat
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] x = new int [] { 1, 2, 3};
            int[] y = new int [] { 4, 5 };


            int itter = 50000;
            Console.WriteLine("test iterations: {0}", itter);

            DateTime startTest = DateTime.Now;
            for(int  i = 0; i < itter; i++)
            {
                int[] z;
                z = x.Concat(y).ToArray();
            }
            Console.WriteLine ("Concat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );

            startTest = DateTime.Now;
            for(int  i = 0; i < itter; i++)
            {
                var vz = new int[x.Length + y.Length];
                x.CopyTo(vz, 0);
                y.CopyTo(vz, x.Length);
            }
            Console.WriteLine ("CopyTo Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks );

            startTest = DateTime.Now;
            for(int  i = 0; i < itter; i++)
            {
                List<int> list = new List<int>();
                list.AddRange(x);
                list.AddRange(y);
                int[] z = list.ToArray();
            }
            Console.WriteLine("list.AddRange Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.Concat(x, y);
            }
            Console.WriteLine("Concat(x, y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.ConcatArrays(x, y);
            }
            Console.WriteLine("ConcatArrays Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.SSConcat(x, y);
            }
            Console.WriteLine("SSConcat Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int k = 0; k < itter; k++)
            {
                int[] three = new int[x.Length + y.Length];

                int idx = 0;

                for (int i = 0; i < x.Length; i++)
                    three[idx++] = x[i];
                for (int j = 0; j < y.Length; j++)
                    three[idx++] = y[j];
            }
            Console.WriteLine("Roll your own Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);


            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.ConcatArraysLinq(x, y);
            }
            Console.WriteLine("ConcatArraysLinq Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] z = Methods.ConcatArraysLambda(x, y);
            }
            Console.WriteLine("ConcatArraysLambda Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                List<int> targetList = new List<int>(x);
                targetList.Concat(y);
            }
            Console.WriteLine("targetList.Concat(y) Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);

            startTest = DateTime.Now;
            for (int i = 0; i < itter; i++)
            {
                int[] result = x.ToList().Concat(y.ToList()).ToArray();
            }
            Console.WriteLine("x.ToList().Concat(y.ToList()).ToArray() Test Time in ticks: {0}", (DateTime.Now - startTest).Ticks);
        }
    }
    static class Methods
    {
        public static T[] Concat<T>(this T[] x, T[] y)
        {
            if (x == null) throw new ArgumentNullException("x");
            if (y == null) throw new ArgumentNullException("y");
            int oldLen = x.Length;
            Array.Resize<T>(ref x, x.Length + y.Length);
            Array.Copy(y, 0, x, oldLen, y.Length);
            return x;
        }

        public static T[] ConcatArrays<T>(params T[][] list)
        {
            var result = new T[list.Sum(a => a.Length)];
            int offset = 0;
            for (int x = 0; x < list.Length; x++)
            {
                list[x].CopyTo(result, offset);
                offset += list[x].Length;
            }
            return result;
        }


        public static T[] SSConcat<T>(this T[] first, params T[][] arrays)
        {
            int length = first.Length;
            foreach (T[] array in arrays)
            {
                length += array.Length;
            }
            T[] result = new T[length];
            length = first.Length;
            Array.Copy(first, 0, result, 0, first.Length);
            foreach (T[] array in arrays)
            {
                Array.Copy(array, 0, result, length, array.Length);
                length += array.Length;
            }
            return result;
        }

        public static T[] ConcatArraysLinq<T>(params T[][] arrays)
        {
            return (from array in arrays
                    from arr in array
                    select arr).ToArray();
        }

        public static T[] ConcatArraysLambda<T>(params T[][] arrays)
        {
            return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
        }
    }

}

Das Ergebnis war:

Geben Sie hier die Bildbeschreibung ein

Wirf deine eigenen Gewinne.

verschmelzen
quelle
Um den Methoden gerecht zu werden, die Methoden verwendet haben, haben die Methoden meinem System wahrscheinlich ungefähr 10.000 Ticks hinzugefügt.
Amalgamate
1
Ich habe Ihren Code in Visual Studio 2013 im Release-Modus ausgeführt und festgestellt, dass das getestete Array, wenn es nicht so klein ist wie Ihr (wie 1000 Elemente), CopyToam schnellsten und ~ 3x schneller als ist Roll your own.
Herr Ree
@ Mr.Ree Ja, mein Array war wirklich winzig, nicht wahr? Vielen Dank. Würde mich interessieren Kopie zu sehen , ob Sperren funktioniert noch besser ...
amalgamate
7

Seien Sie vorsichtig mit der ConcatMethode. Die Post- Array-Verkettung in C # erklärt Folgendes :

var z = x.Concat(y).ToArray();

Wird für große Arrays ineffizient sein. ConcatDies bedeutet, dass die Methode nur für Arrays mit mittlerer Größe (bis zu 10000 Elemente) gilt.

kurdishTree
quelle
2
Was ist mit Arrays mit mehr als 10.000 Elementen zu tun?
Alex
6
public static T[] Concat<T>(this T[] first, params T[][] arrays)
{
    int length = first.Length;
    foreach (T[] array in arrays)
    {
        length += array.Length;
    }
    T[] result = new T[length];
    length = first.Length;
    Array.Copy(first, 0, result, 0, first.Length);
    foreach (T[] array in arrays)
    {
        Array.Copy(array, 0, result, length, array.Length);
        length += array.Length;
    }
    return result;
}
Sergey Shteyn
quelle
2
Bei StackOverflow fügen Sie bitte nicht nur Code ein, sondern erläutern auch Ihren Ansatz. In diesem speziellen Fall müssen Sie möglicherweise auch erklären, was Ihre späte Antwort zu den bereits gegebenen (und akzeptierten) Antworten hinzufügt
Gert Arnold
1
Ich bin mir nicht sicher, was dieses "dies" vor dem ersten Parameter tut, aber im Übrigen ist dies eine ausgezeichnete Funktion. Generisch und mit unendlich vielen Parametern.
Nyerguds
2
Hallo Nyerguds. Um Ihre Frage zu beantworten, wird das Schlüsselwort "this" verwendet, um die Funktion zu einer Erweiterungsmethode zu machen. Weitere Informationen zu Erweiterungsmethoden finden Sie in diesem MSDN-Artikel
JFish222
6

Effizientere (schneller) zu verwenden , Buffer.BlockCopyüber Array.CopyTo,

int[] x = new int [] { 1, 2, 3};
int[] y = new int [] { 4, 5 };

int[] z = new int[x.Length + y.Length];
var byteIndex = x.Length * sizeof(int);
Buffer.BlockCopy(x, 0, z, 0, byteIndex);
Buffer.BlockCopy(y, 0, z, byteIndex, y.Length * sizeof(int));

Ich habe ein einfaches Testprogramm geschrieben, das "den Jitter erwärmt", im Release-Modus kompiliert und ohne angeschlossenen Debugger auf meinem Computer ausgeführt.

Für 10.000.000 Iterationen des Beispiels in der Frage

Concat dauerte 3088ms

CopyTo dauerte 1079 ms

BlockCopy dauerte 603 ms

Wenn ich die Testarrays auf zwei Sequenzen von 0 bis 99 ändere, erhalte ich ähnliche Ergebnisse.

Concat dauerte 45945ms

CopyTo dauerte 2230 ms

BlockCopy dauerte 1689 ms

Aus diesen Ergebnissen kann ich behaupten, dass die CopyTound BlockCopyMethoden wesentlich effizienter sind als Concatund darüber hinaus, wenn Leistung ein Ziel BlockCopyist, Wert über haben CopyTo.

Um diese Antwort einzuschränken, wählen Sie die Methode, die Sie am einfachsten finden, wenn die Leistung keine Rolle spielt oder nur wenige Iterationen stattfinden. Buffer.BlockCopybietet ein Dienstprogramm für die Typkonvertierung, das über den Rahmen dieser Frage hinausgeht.

Jodrell
quelle
6

Späte Antwort :-).

public static class ArrayExtention
    {

        public static T[] Concatenate<T>(this T[] array1, T[] array2)
        {
            T[] result = new T[array1.Length + array2.Length];
            array1.CopyTo(result, 0);
            array2.CopyTo(result, array1.Length);
            return result;
        }

    }
Saleh Saeednia
quelle
3

Die effizienteste Struktur in Bezug auf RAM (und CPU), um das kombinierte Array zu halten, wäre eine spezielle Klasse, die IEnumerable implementiert (oder wenn Sie sogar von Array ableiten möchten) und intern mit den ursprünglichen Arrays verknüpft ist, um die Werte zu lesen. AFAIK Concat macht genau das.

In Ihrem Beispielcode könnten Sie jedoch .ToArray () weglassen, was es effizienter machen würde.

TToni
quelle
3

Es tut mir leid, einen alten Thread wiederzubeleben, aber wie wäre es damit:

static IEnumerable<T> Merge<T>(params T[][] arrays)
{
    var merged = arrays.SelectMany(arr => arr);

    foreach (var t in merged)
        yield return t;
}

Dann in Ihrem Code:

int[] x={1, 2, 3};
int[] y={4, 5, 6};

var z=Merge(x, y);  // 'z' is IEnumerable<T>

var za=z.ToArray(); // 'za' is int[]

Bis Sie nennen .ToArray(), .ToList()oder .ToDictionary(...)ist der Speicher nicht zugeordnet sind , können Sie auf „Ihre Abfrage zu erstellen“ und entweder Aufruf einer dieser drei , um es auszuführen oder einfach gehen durch sie alle durch die Verwendung foreach (var i in z){...}von der Klausel , die zu einem Zeitpunkt ein Element zurückgibtyield return t; über...

Die obige Funktion kann wie folgt in eine Erweiterung umgewandelt werden:

static IEnumerable<T> Merge<T>(this T[] array1, T[] array2)
{
    var merged = array1.Concat(array2);

    foreach (var t in merged)
        yield return t;
}

Im Code können Sie also Folgendes tun:

int[] x1={1, 2, 3};
int[] x2={4, 5, 6};
int[] x3={7, 8};

var z=x1.Merge(x2).Merge(x3);   // 'z' is IEnumerable<T>

var za=z.ToArray(); // 'za' is int[]

Der Rest ist der gleiche wie zuvor.

Eine weitere Verbesserung würde dies sich ändern T[]in IEnumerable<T>(so das params T[][]werden würde params IEnumerable<T>[]) , um diese Funktionen zu machen akzeptieren mehr als nur Arrays.

Hoffe das hilft.

Nurchi
quelle
2

Sie können es so machen, wie Sie es erwähnt haben, oder wenn Sie wirklich manuell darüber erfahren möchten, können Sie Ihre eigene Schleife rollen:

        string[] one = new string[] { "a", "b" };
        string[] two = new string[] { "c", "d" };
        string[] three;

        three = new string[one.Length + two.Length];

        int idx = 0;

        for (int i = 0; i < one.Length; i++)
            three[idx++] = one[i];
        for (int j = 0; j < two.Length; j++)
            three[idx++] = two[j];
Dreadwail
quelle
@nawfal Ich denke, das hängt von der Array-Größe ab. Dies hat meinen kleinen Array-Test gewonnen.
Amalgamat
2

Ich habe eine elegante einzeilige Lösung mit LINQ- oder Lambda- Ausdruck gefunden, beide funktionieren gleich (LINQ wird beim Kompilieren des Programms in Lambda konvertiert). Die Lösung funktioniert für jeden Array-Typ und für eine beliebige Anzahl von Arrays.

Verwenden von LINQ:

public static T[] ConcatArraysLinq<T>(params T[][] arrays)
{
    return (from array in arrays
            from arr in array
            select arr).ToArray();
}

Verwenden von Lambda:

public static T[] ConcatArraysLambda<T>(params T[][] arrays)
{
    return arrays.SelectMany(array => array.Select(arr => arr)).ToArray();
}

Ich habe beides nach Belieben bereitgestellt. Performance weise @Sergey Shteyn des oder @ deepee1 Die Lösungen sind ein bisschen schneller, Lambda Ausdruck der langsamste ist. Die benötigte Zeit hängt vom Typ (den Typen) der Array-Elemente ab. Wenn jedoch nicht Millionen von Aufrufen vorliegen, gibt es keinen signifikanten Unterschied zwischen den Methoden.

Marko Grešak
quelle
1

Was Sie beachten müssen, ist, dass Sie bei Verwendung von LINQ eine verzögerte Ausführung verwenden. Die anderen hier beschriebenen Methoden funktionieren alle einwandfrei, werden jedoch sofort ausgeführt. Darüber hinaus ist die Concat () - Funktion wahrscheinlich so optimiert, wie Sie es nicht selbst tun können (Aufrufe interner APIs, Betriebssystemaufrufe usw.). Wie auch immer, wenn Sie nicht wirklich versuchen müssen, zu optimieren, befinden Sie sich derzeit auf dem Weg zur "Wurzel allen Übels";)

Siewers
quelle
1

Versuche Folgendes:

T[] r1 = new T[size1];
T[] r2 = new T[size2];

List<T> targetList = new List<T>(r1);
targetList.Concat(r2);
T[] targetArray = targetList.ToArray();
کی‌راد عباسی
quelle
1

Hier ist meine Antwort:

int[] z = new List<string>()
    .Concat(a)
    .Concat(b)
    .Concat(c)
    .ToArray();

Diese Methode kann auf Initialisierungsebene verwendet werden, um beispielsweise eine statische Verkettung statischer Arrays zu definieren:

public static int[] a = new int [] { 1, 2, 3, 4, 5 };
public static int[] b = new int [] { 6, 7, 8 };
public static int[] c = new int [] { 9, 10 };

public static int[] z = new List<string>()
    .Concat(a)
    .Concat(b)
    .Concat(c)
    .ToArray();

Es gibt jedoch zwei Einschränkungen, die Sie berücksichtigen müssen:

  • Die Concat Methode erstellt einen Iterator über beide Arrays: Sie erstellt kein neues Array und ist somit hinsichtlich des verwendeten Speichers effizient. Die nachfolgende Methode  ToArray  negiert jedoch diesen Vorteil, da tatsächlich ein neues Array erstellt wird und der Speicher für das Array belegt wird neues Array.
  • Wie @Jodrell sagte, Concatwäre es für große Arrays eher ineffizient: Es sollte nur für mittelgroße Arrays verwendet werden.

Wenn das Streben nach Leistung ein Muss ist, kann stattdessen die folgende Methode verwendet werden:

/// <summary>
/// Concatenates two or more arrays into a single one.
/// </summary>
public static T[] Concat<T>(params T[][] arrays)
{
    // return (from array in arrays from arr in array select arr).ToArray();

    var result = new T[arrays.Sum(a => a.Length)];
    int offset = 0;
    for (int x = 0; x < arrays.Length; x++)
    {
        arrays[x].CopyTo(result, offset);
        offset += arrays[x].Length;
    }
    return result;
}

Oder (für Einzeiler-Fans):

int[] z = (from arrays in new[] { a, b, c } from arr in arrays select arr).ToArray();

Obwohl die letztere Methode viel eleganter ist, ist die erstere definitiv besser für die Leistung.

Weitere Informationen finden Sie in diesem Beitrag in meinem Blog.

Darkseal
quelle
0

Für int [] sieht das, was du getan hast, für mich gut aus. Astanders Antwort würde auch gut funktionieren für List<int>.

Mezoid
quelle
2
Concat würde auch für List <int> funktionieren. Das ist das Tolle an Concat, es funktioniert auf jedem IEnumerable <>
Mike Two
0

Für kleinere Arrays <10000 Elemente:

using System.Linq;

int firstArray = {5,4,2};
int secondArray = {3,2,1};

int[] result = firstArray.ToList().Concat(secondArray.ToList()).toArray();
Michail Michailidis
quelle
Warum Linq verwenden, wenn Sie nicht müssen?!
Ina
0
static class Extensions
{
    public static T[] Concat<T>(this T[] array1, params T[] array2) => ConcatArray(array1, array2);

    public static T[] ConcatArray<T>(params T[][] arrays)
    {
        int l, i;

        for (l = i = 0; i < arrays.Length; l += arrays[i].Length, i++);

        var a = new T[l];

        for (l = i = 0; i < arrays.Length; l += arrays[i].Length, i++)
            arrays[i].CopyTo(a, l);

        return a;
    }
}

Ich denke, die obige Lösung ist allgemeiner und leichter als die anderen, die ich hier gesehen habe. Es ist allgemeiner, weil es die Verkettung nicht nur für zwei Arrays einschränkt und leichter ist, weil es weder LINQ noch List verwendet.

Beachten Sie, dass die Lösung präzise ist und die hinzugefügte Allgemeinheit keinen signifikanten Laufzeitaufwand verursacht.

Drowa
quelle
Ich würde empfehlen, nach neueren Fragen zu suchen, oder solche, die noch nicht viele Antworten haben - einschließlich einer, die Ihrer ziemlich ähnlich ist.
Andrew Barber
Ich habe diese Lösung vorgeschlagen, weil ich denke, dass sie zusammenfasst, was von den anderen gut ist. Es wurde hergestellt.
Drowa
-2

int [] x = new int [] {1, 2, 3}; int [] y = new int [] {4, 5};

int [] z = x.Union (y) .ToArray ();

Milad Doraki
quelle
2
UnionDies ist keine sehr gute Möglichkeit, da implizit Distinctalle Duplikate aus der verknüpften Sammlung aufgerufen und entfernt werden. Concatist viel besser, aber es ist bereits in der ursprünglichen Frage.
Nurchi
-2
int[] scores = { 100, 90, 90, 80, 75, 60 };
int[] alice = { 50, 65, 77, 90, 102 };
int[] scoreBoard = new int[scores.Length + alice.Length];

int j = 0;
for (int i=0;i<(scores.Length+alice.Length);i++)  // to combine two arrays
{
    if(i<scores.Length)
    {
        scoreBoard[i] = scores[i];
    }
    else
    {
        scoreBoard[i] = alice[j];
        j = j + 1;

    }
}


for (int l = 0; l < (scores.Length + alice.Length); l++)
{
    Console.WriteLine(scoreBoard[l]);
}
Prestige Prajna
quelle