[解決済み】C#で2つ以上のバイト配列を結合する最良の方法
質問
C#で3つのバイト配列があり、1つにまとめる必要があります。このタスクを完了するための最も効率的な方法は何でしょうか?
どのように解決するのですか?
プリミティブ型(バイトを含む)の場合は
System.Buffer.BlockCopy
の代わりに
System.Array.Copy
. より速くなりました。
10バイトずつの配列を3つ使って100万回実行するループで、提案された各方法の時間を計ってみました。以下はその結果です。
-
を使用した新しいバイト配列
System.Array.Copy
- 0.2187556秒 -
を使用した新しいバイト配列
System.Buffer.BlockCopy
- 0.1406286秒 - IEnumerable<byte> をC#のyield演算子で使用する - 0.0781270秒
- IEnumerable<byte> LINQのConcat<>を使用 - 0.0781270秒
各配列のサイズを100要素に増やして、テストを再実行しました。
-
を使用した新しいバイト配列
System.Array.Copy
- 0.2812554秒 -
を使用した新しいバイト配列
System.Buffer.BlockCopy
- 0.2500048秒 - IEnumerable<byte> をC#のyield演算子で使用 - 0.0625012秒
- IEnumerable<byte> LINQのConcat<>を使用 - 0.0781265秒
各配列のサイズを1000要素に増やして、テストを再実行しました。
-
を使用した新しいバイト配列
System.Array.Copy
- 1.0781457秒 -
を使用した新しいバイト配列
System.Buffer.BlockCopy
- 1.0156445秒 - IEnumerable<byte> をC#のyield演算子で使用 - 0.0625012秒
- IEnumerable<byte> LINQのConcat<>を使用 - 0.0781265秒
最後に、各配列のサイズを100万要素まで増やし、各ループを実行しながらテストを再実行しました。 のみ 4000回。
-
を使用した新しいバイト配列
System.Array.Copy
- 13.4533833秒 -
を使用した新しいバイト配列
System.Buffer.BlockCopy
- 13.1096267秒 - IEnumerable<byte> をC#のyield演算子で使用する - 0秒
- IEnumerable<byte> LINQのConcat<>を使用する - 0秒
したがって、新しいバイト配列が必要な場合は、次のようにします。
byte[] rv = new byte[a1.Length + a2.Length + a3.Length];
System.Buffer.BlockCopy(a1, 0, rv, 0, a1.Length);
System.Buffer.BlockCopy(a2, 0, rv, a1.Length, a2.Length);
System.Buffer.BlockCopy(a3, 0, rv, a1.Length + a2.Length, a3.Length);
しかし、もし
IEnumerable<byte>
,
間違いなく
は、LINQのConcat<>メソッドの方が好きです。C#のyield演算子より少し遅いだけで、より簡潔で、よりエレガントです。
IEnumerable<byte> rv = a1.Concat(a2).Concat(a3);
任意の数の配列があり、.NET 3.5を使用している場合、その配列を
System.Buffer.BlockCopy
の解決策をより汎用的にするために、次のようにします。
private byte[] Combine(params byte[][] arrays)
{
byte[] rv = new byte[arrays.Sum(a => a.Length)];
int offset = 0;
foreach (byte[] array in arrays) {
System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);
offset += array.Length;
}
return rv;
}
*注:上記のブロックが動作するためには、次の名前空間を先頭に追加する必要があります。
using System.Linq;
Jon Skeetの、後続のデータ構造(バイト配列対IEnumerable<byte>)の反復に関する指摘に対して、私は最後のタイミングテスト(100万要素、4000反復)を再実行し、各パスで配列全体にわたって反復するループを追加しました。
-
を使用した新しいバイト配列
System.Array.Copy
- 78.20550510秒 -
を使用した新しいバイト配列
System.Buffer.BlockCopy
- 77.89261900秒 - IEnumerable<byte> C#のyield演算子を使用 - 551.7150161秒
- IEnumerable<byte> LINQのConcat<>を使用する - 448.1804799 秒
要は、それは VERY の両方の効率性を理解することが重要です。 と使用方法 のデータ構造です。作成時の効率に注目するだけでは、使用時の非効率性を見落としてしまう可能性があるのです。ジョン、ありがとうございます。
関連
-
[解決済み】「入力文字列が正しい形式ではありませんでした」エラーの解決方法は?[重複しています]。
-
[解決済み】ランダムなブーリアンを生成する最速の方法
-
[解決済み] JavaScript で配列に値が含まれているかどうかを確認するにはどうすればよいですか?
-
[解決済み] 配列からArrayListを作成する
-
[解決済み] JavaScriptの配列で一意な値をすべて取得する(重複を排除する)。
-
[解決済み] JavaScriptで配列の先頭に新しい配列要素を追加するにはどうすればよいですか?
-
[解決済み] 配列の結合/平坦化
-
[解決済み】オブジェクトの配列を文字列のプロパティ値でソートする
-
[解決済み】大文字・小文字を区別しない「Contains(string)
-
[解決済み】JavaScriptで2つの配列を結合し、項目の重複を排除する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】エラー。「戻り値を変更できません」 C#
-
[解決済み】"出力タイプがクラスライブラリのプロジェクトは直接起動できない"
-
[解決済み] エンティティタイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】SmtpException: トランスポート接続からデータを読み取れません:net_io_connectionclosed
-
[解決済み】バックスラッシュを含むパス文字列のエスケープシーケンスが認識されない件
-
[解決済み】Entity FrameworkからのSqlException - セッション内で他のスレッドが動作しているため、新しいトランザクションは許可されません。
-
[解決済み】Visual Studio: 操作を完了できませんでした。パラメータが正しくありません
-
[解決済み】OnCollisionEnter2Dが実行されない?
-
[解決済み] [Solved] .NETでスレッドの終了を待つには?
-
[解決済み】.NETで2つの配列をマージする