2011-01-12 9 views
1

C#の2次元配列(非ぎざぎざ)を1dに平坦化して戻す効率的な方法を知っている人はいませんか?私はバックエンドでC#が1d配列として保持しなければならないことを知っています。可能であれば、バックエンド1d配列のハンドルを取得したいと思います。byte [、]をbyte []に​​変換する

私がこれをやりたいのは、管理されたコードで2dを持つことができたいと思っているからです。時には、管理されていないdllのインポートされたコード(最適化されています)デジタル画像処理における組み立ては良い例です)。そして、最も簡単なだけの値を一つずつコピーし、あなたのアレイを反復することである

int x = i % width; 
int y = i/width; 

int i = y * width + x; 

バック:1Dインデックスに2Dインデックスから行くために

+0

なぜこれを行う必要がありますか? – Oded

+2

"私はバックエンドでC#が1d配列としてそれを保持しなければならないことを知っています"あなたはそれをどう思いますか?それはまったく当てはまる必要はありません。 – jason

+1

@ Jason:実際には、仕様の次の行は、基礎となる表現が線形配列であると仮定できると示唆しているようです。 §18.6より:「配列が格納される方法を考えると、任意の次元の配列を線形であるかのように扱うことができます。しかし、これは事実である必要はありませんが、それが本当であることは非常に良いことに注意してください。 – jason

答えて

3

byte[,]から管理されたbyte[]の配列をコピーすることはできません(私には分かりません)。

あなたがunsafeコードに慣れ場合は、アレイ上byte*を修正することができ、私はそれが動作するはずと信じて:

fixed (byte* ptr = array) 
{ 
    for (int i = 0; i < N; ++i) 
    { 
     byte b = ptr[i]; 
     // Do whatever you need. 
    } 
} 
+0

これがうまくいけば、これは私が必要としていたものです。 – dko

+0

@dko:うまくいきます。 Jon Skeetの回答:http://stackoverflow.com/questions/4674394/convert-byte-to-byte/4674427#4674427をご覧ください。 – jason

+0

@ Jason行のメジャーまたは列の大部分の順序で格納されているかどうか知っていますか? AKAバイト[5,5] temp、temp [0,3]を3バイト目または15バイト目に索引付けしますか? – dko

3

+0

これは、データをコピーするのに最も効率的な方法とはほど遠いものです。 –

+1

@Jon Skeet:実際に私はBuffer.BlockCopyを見たことがないので、私はそのパフォーマンスを測定していません。私はそれが速いがあなたの言葉を取るよ。 :)違いが何であるかを見るためにいくつかのパフォーマンス番号を見るのは興味深いでしょう。私はこの質問がたくさん出てくることを覚えています(この質問は実際には重複していると確信していますが、今は別のものを見つけることができません)。 –

+0

はい、これは私が効率的な方法として言及していたものとは遠いです。 – dko

11

オブジェクト自体は、1つの連続したメモリブロックにデータ自体があるにもかかわらず、byte[]ではありません。アレイはそのランクと長さなども知っていることを忘れないでください。

ただし、Buffer.BlockCopyを使用すると、アレイをすばやくコピーできます。例えば:最後の引数は、バイトの数ではなく、配列の要素の数であることを

byte[,] source = new byte[5,5]; 
byte[] dest = new byte[source.Length]; 
Buffer.BlockCopy(source, 0, dest, 0, source.Length); 

注意。

+0

§18.6の仕様からの関連する行: "配列が格納される方法を考えると、任意の次元の配列を線形であるかのように扱うことができます。"特に、 'byte [] destination = new byte [source.Length];と言うことができます。 unsafe {fixed(byte * p = source){for(int i = 0; i jason

+0

また、明らかに '' byte [] dest = new byte [source.Length];と '' Buffer.BlockCopy(source、0、dest、0、source.Length * sizeof(byte)); ' – jason

+0

@ジェイソン:はい、それは本当です - 私は 'sizeof(byte)'を気にしませんでしたが...多分それほど些細ではないかもしれません:) –

0
var myFlattenedByteArray = my2DByteArray.SelectMany(b=>b).ToArray(); 

これは、2Dバイト配列の各サブアレイの各要素を返します。サブ配列要素の順序で指定します。myFlattenedByteArray [1] == my2DByteArray [0] [1]。おそらく、よりパフォーマンスの高い、または効率的なソリューション(特に、SelectManyによって独自のArrayに生成されたEnumerableのスラップリング)がありますが、これは1つのライナーです。

関連する問題