webentwicklung-frage-antwort-db.com.de

Die effizienteste Methode zum Anhängen von Arrays in C #?

Ich ziehe Daten aus einem ActiveX der alten Schule in Form von Arrays von Doppelten. Die endgültige Anzahl der Proben, die ich tatsächlich abrufen werde, ist mir zunächst nicht bekannt.

Was ist die effizienteste Methode, um diese Arrays in C # zu verknüpfen, wenn ich sie aus dem System hole?

63
Huck

Sie können nicht an ein tatsächliches Array anhängen - die Größe eines Arrays wird beim Erstellen festgelegt. Verwenden Sie stattdessen ein List<T> was wachsen kann, wie es muss.

Alternativ können Sie eine Liste von Arrays führen und diese nur dann miteinander verknüpfen, wenn Sie alles erfasst haben.

Siehe Eric Lipperts Blogpost über Arrays für mehr Details und Einsichten, als ich realistischerweise bereitstellen könnte :)

77
Jon Skeet

Ich glaube, wenn Sie zwei Arrays desselben Typs haben, die Sie zu einem dritten Array kombinieren möchten, gibt es eine sehr einfache Möglichkeit, dies zu tun.

hier ist der Code:

String[] theHTMLFiles = Directory.GetFiles(basePath, "*.html");
String[] thexmlFiles = Directory.GetFiles(basePath, "*.xml");
List<String> finalList = new List<String>(theHTMLFiles.Concat<string>(thexmlFiles));
String[] finalArray = finalList.ToArray();
28
Michael Bahig

Ich empfehle die hier gefundene Antwort: Wie verkette ich zwei Arrays in C #?

z.B.

var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);
25
GeorgePotter

Das Verketten von Arrays ist mit den im Lieferumfang von .Net 4 enthaltenen Linq-Erweiterungen ganz einfach

Das Wichtigste, an das Sie sich erinnern sollten, ist, dass linq mit IEnumerable<T> - Objekten arbeitet. Um also ein Array als Ergebnis zurückzuerhalten, müssen Sie am Ende die .ToArray() -Methode verwenden

Beispiel für die Verkettung von Zwei-Byte-Arrays:

byte[] firstArray = {2,45,79,33};
byte[] secondArray = {55,4,7,81};
byte[] result = firstArray.Concat(secondArray).ToArray();
22
Lenny Woods

Die Lösung sieht nach viel Spaß aus, aber es ist möglich, Arrays in nur zwei Anweisungen zu verketten. Wenn Sie Arrays mit großen Bytes verarbeiten, ist es wahrscheinlich ineffizient, eine verknüpfte Liste zu verwenden, um jedes Byte zu enthalten.

Hier ist ein Codebeispiel zum Lesen von Bytes aus einem Stream und zum direkten Erweitern eines Bytearrays:

 Byte [] Buf = Neues Byte [8192]; 
 Byte [] Ergebnis = Neues Byte [0]; 
 Int Count = 0; 
 Do 
 {
 count = resStream.Read (buf, 0, buf.Length); 
 if (count! = 0) 
 {
 Array.Resize (ref result, result.Length + count); 
 Array.Copy (buf, 0, result, result.Length - count, count); 
} 
} 
 while (Anzahl> 0); // weitere Daten zum Lesen? 
 resStream.Close (); 
7
Hugo

Hiermit können wir zwei Arrays ohne jede Schleife hinzufügen.

Ich glaube, wenn Sie zwei Arrays desselben Typs haben, die Sie zu einem Array kombinieren möchten, gibt es eine sehr einfache Möglichkeit, dies zu tun.

Hier ist der Code:

String[] TextFils = Directory.GetFiles(basePath, "*.txt");
String[] ExcelFils = Directory.GetFiles(basePath, "*.xls");
String[] finalArray = TextFils.Concat(ExcelFils).ToArray();

oder

String[] Fils = Directory.GetFiles(basePath, "*.txt");
String[] ExcelFils = Directory.GetFiles(basePath, "*.xls");
Fils = Fils.Concat(ExcelFils).ToArray();
6
SGRao

Wenn Sie die Anzahl der Elemente, die am Ende vorhanden sein werden, näherungsweise bestimmen können, verwenden Sie die Überladung des List-Konstruktors, die als Parameter gezählt wird. Sie sparen einige teure Listenduplikationen. Sonst muss man dafür bezahlen.

4
Olmo

Möglicherweise müssen Sie das Endergebnis nicht in ein zusammenhängendes Array verketten. Hänge stattdessen weiter an die Liste an, wie von Jon vorgeschlagen. Am Ende haben Sie ein gezacktes Array (na ja, eigentlich fast rechteckig). Wenn Sie über einen Index auf ein Element zugreifen müssen, verwenden Sie das folgende Indexierungsschema:

double x = list[i / sampleSize][i % sampleSize];

Das Iterieren über gezackte Arrays ist ebenfalls einfach:

for (int iRow = 0; iRow < list.Length; ++iRow) {
  double[] row = list[iRow];
  for (int iCol = 0; iCol < row.Length; ++iCol) {
    double x = row[iCol];
  }
}

Dies erspart Ihnen die Speicherzuweisung und das Kopieren auf Kosten eines etwas langsameren Elementzugriffs. Ob dies ein Nettoleistungsgewinn ist, hängt von der Größe Ihrer Daten, den Datenzugriffsmustern und den Speicherbeschränkungen ab.

4
Constantin

Hier ist eine verwendbare Klasse, basierend auf dem, was Constantin gesagt hat:

class Program
{
    static void Main(string[] args)
    {
        FastConcat<int> i = new FastConcat<int>();
        i.Add(new int[] { 0, 1, 2, 3, 4 });
        Console.WriteLine(i[0]);
        i.Add(new int[] { 5, 6, 7, 8, 9 });
        Console.WriteLine(i[4]);

        Console.WriteLine("Enumerator:");
        foreach (int val in i)
            Console.WriteLine(val);

        Console.ReadLine();
    }
}

class FastConcat<T> : IEnumerable<T>
{
    LinkedList<T[]> _items = new LinkedList<T[]>();
    int _count;

    public int Count
    {
        get
        {
            return _count;
        }
    }

    public void Add(T[] items)
    {
        if (items == null)
            return;
        if (items.Length == 0)
            return;

        _items.AddLast(items);
        _count += items.Length;
    }

    private T[] GetItemIndex(int realIndex, out int offset)
    {
        offset = 0; // Offset that needs to be applied to realIndex.
        int currentStart = 0; // Current index start.

        foreach (T[] items in _items)
        {
            currentStart += items.Length;
            if (currentStart > realIndex)
                return items;
            offset = currentStart;
        }
        return null;
    }

    public T this[int index]
    {
        get
        {
            int offset;
            T[] i = GetItemIndex(index, out offset);
            return i[index - offset];
        }
        set
        {
            int offset;
            T[] i = GetItemIndex(index, out offset);
            i[index - offset] = value;
        }
    }

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
        foreach (T[] items in _items)
            foreach (T item in items)
                yield return item;
    }

    #endregion

    #region IEnumerable Members

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

    #endregion
}

Olmos Vorschlag ist sehr gut, aber ich würde Folgendes hinzufügen: Wenn Sie nicht sicher sind, welche Größe Sie haben, ist es besser, sie ein wenig größer als ein wenig kleiner zu machen. Wenn eine Liste voll ist, denken Sie daran, dass sie doppelt so groß ist, um weitere Elemente hinzuzufügen.

Beispiel: Angenommen, Sie benötigen ungefähr 50 Elemente. Wenn Sie eine Größe von 50 Elementen verwenden und die endgültige Anzahl von Elementen 51 beträgt, erhalten Sie eine Liste mit 100 Elementen und 49 verschwendeten Positionen.

0
rgargente