Das verketten einer C# - Liste von byte[]
Ich bin mehrere byte-arrays, die müssen miteinander verbunden werden, erstellen Sie ein großes byte-array - würde ich lieber nicht verwenden, byte[]'s bei allen-aber Sie haben keine Wahl hier...
Ich füge jeden ein, um eine Liste wie ich Sie erschaffen, damit ich nur die Verkettung, wenn ich alle byte[]'s, aber meine Frage ist, was ist der beste Weg tatsächlich, dies zu tun?
Wenn ich eine Liste habe mit einer unbekannten Anzahl von byte[]'s und ich möchte concat Sie alle zusammen.
Dank.
InformationsquelleAutor Adam Cobb | 2011-02-02
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der obige code verketten eine Abfolge von Sequenzen von bytes, die in einer Sequenz - und speichern das Ergebnis in einem array.
Obwohl lesbar, dies ist nicht maximal effizient - es ist nicht mit der Tatsache, dass Sie schon wissen die Länge der resultierende byte-array und kann somit vermeiden, die dynamisch erweitert
.ToArray()
Implementierung, die notwendigerweise mehrere Zuweisungen und array-Kopien. Darüber hinausSelectMany
implementiert ist, in Bezug auf Iteratoren; dies bedeutet, dass viele+viele Schnittstellen-Aufrufe, die ist ziemlich langsam. Jedoch für kleine-ish-Daten-set-Größe dürfte dies egal.Wenn brauchst du eine schnellere Umsetzung können Sie Folgendes tun:
oder wie Martinho schon sagt:
Einige timings:
Nutzt die kurze Methode zum verketten diese 500500 bytes dauert 15ms, mit der fast-Methode dauert 0,5 ms auf meinem Rechner - YMMV, und beachten Sie, dass für viele Anwendungen sind beide mehr als schnell genug ;-).
Schließlich könnten Sie ersetzen
Array.CopyTo
mit derstatic
Array.Copy
, die low-level -Buffer.BlockCopy
oder eineMemoryStream
mit einem reserviert-zurück-Puffer - diese führen alle so ziemlich gleich auf meine tests (x64 .NET 4.0).Was ist die "traditionelle Lösung"?
Die "traditionelle" Lösung wäre wahrscheinlich die manuelle, verschachtelte for-Schleifen. Das ist etwa drei mal langsamer als der block-copy-basierte Lösungen, die aber immer noch 10 mal schneller als
SelectMany
.InformationsquelleAutor Eamon Nerbonne
Hier ist eine Lösung basierend auf Andrew Bezzub's und fejesjoco Antworten, pre-allocating alle nötigen Speicher vor. Damit ergibt sich Θ(N) Speicher und Θ(N) Zeit (wobei N die Gesamtzahl von bytes).
InformationsquelleAutor R. Martinho Fernandes
schreiben Sie alles in ein MemoryStream-statt einer Liste. dann rufen Sie MemoryStream.ToArray(). Oder wenn Sie die Liste zunächst eine Zusammenfassung der byte-array-Längen, erstellen Sie ein neues byte-array mit der gesamten Länge, und kopieren Sie jedes array nach der letzten in der großen array.
InformationsquelleAutor fejesjoco
Linq:
Vielleicht eine schnellere Lösung wäre (nicht das deklarieren von array im Voraus):
Scheint es, wie oben würden Durchlaufen jedes array nur einmal.
Beachten Sie, dass dieser Lösung ist O(n^2) in die Anzahl von byte-arrays. (Sehen Sie, warum? Hinweis: Sequenz-Operatoren sind faul.) Sie können es besser als die. Können Sie eine Lösung finden, die linear in der Anzahl der byte arrays?
danke! Es war nicht offensichtlich für mich, dass die Lösung ist O(n^2). Was ist, wenn ich verwenden Sie separate Methode, um zählbare form von bytes? Ich aktualisierte die Antwort.
Was ist Faulheit hat das damit zu tun? Non-lazy-Implementierung O(N^2) zu. Umgekehrt könnten Sie haben ein faul-Sequenz und O(N) Leistung. Das problem ist die benötigte Schnittstelle Verpackung - Sie müssen sukzessive wrap-Zähler - Sie können nicht erklären, eine Fortsetzung. Es ist nicht ganz fairer Vergleich, aber in, sagen wir, Haskell konzeptionell ähnlichen code würde zum Beispiel so faul, und O(N).
Natürlich könnte man verallgemeinern, dass auch weitere IEnumerable<R> Flatten<T R>(IEnumerable<T> Elemente, Func<T, IEnumerable<R>> selector) { foreach(T item in items) foreach(R Ergebnis im Selektor(Element)) yield return result; } und hey, Sie nur erfunden SelectMany; diese Methode ist bereits in der Sequenz-operator-Bibliothek.
InformationsquelleAutor Andrew Bezzub
Statt der Speicherung jedes byte-array in eine
List<byte[]>
, könnten Sie stattdessen fügen Sie Sie direkt auf eineList<byte>
mit der AddRange Methode für jeden.InformationsquelleAutor Justin
hmm, wie etwa Liste.addrange?
Tut AddRange konvertieren einer Liste in ein byte[]? Nein.
InformationsquelleAutor Fredou