2

配列テーブルを作成したいという問題に遭遇しました。これは、テーブルを作成する前に実行時に行と列の数がわかっている 2 次元配列です。列数はすべての行で同じです。

配列が作成されたら、その配列の 1 つの次元だけを操作したいと思います。おそらく、メソッドへの参照を渡します。

以下は架空の例です。

// Create a table 3x3 table.
int[,] DistanceTable = new int[3, 3];
DistanceTable[0, 0] = 0;
DistanceTable[1, 1] = 0;
DistanceTable[2, 2] = 0;

DistanceTable[0, 1] = 10;
DistanceTable[0, 2] = 40;

DistanceTable[1, 0] = 10;
DistanceTable[1, 2] = 25;

DistanceTable[2, 0] = 40;
DistanceTable[2, 1] = 25;

// Why can't I do this?
int[] twos = DistanceTable[2];

JaggedArray (Array-of-Arrays) を使用すると、これが可能になります。しかし、多次元配列は常に各行の列数が同じであるため、JaggedArray は必要ありません。

これを行うことは可能ですか?そうでない場合、なぜですか?

ありがとう

4

5 に答える 5

3

いいえ。多次元配列は、行優先順序を使用して 1 つのメモリ ブロックに順番に格納されるという点で、ジャグ配列とは異なります。

このため、データの 1 つの「列」を引き出すには、これを引き出すためにスキップする必要があります。

一方、ジャグ配列は、2 番目の配列への参照の配列です。これにより、ジャグ配列から個々の「配列」を簡単に引き出すことができます。

しかし、多次元配列は常に各行の列数が同じであるため、JaggedArray は必要ありません。

.NET のジャグ配列には、パフォーマンスが大幅に最適化されています。多くの場合、多次元配列よりも優れています。これが、ほとんどのコード分析ルーチンが 2 次元配列からジャグ配列への変換を提案する理由です。「必要」でなくても、これを検討する価値があります。

于 2010-10-18T23:40:09.900 に答える
2

これは不可能です; 多次元配列はそのようには機能しません。

一般に、常にジャグ配列を使用する必要があります。彼らはより速いです。
(JITter は、メソッド呼び出しの代わりに生のメモリ アクセス命令を生成します)

于 2010-10-18T23:37:49.953 に答える
1

申し訳ありませんが、これは実際にはC#で多次元配列の単一次元への参照を取得するにはどうすればよいですか?へのコメントである必要があります。しかし、私はまだコメントすることを許可されていません..

とにかく、ギザギザ配列の方がパフォーマンスが優れている理由は、いくつかの説明の後、簡単に理解できます。多次元配列を調べてみましょう。

{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}

メモリには、{0, 1, 2, 3, 4, 5, 6, 7, 8} のように保存されます。

[0, 0] にアクセスしたい場合、メモリ内のどこを読み取るのでしょうか? アドレスを計算する必要があります: y * 3 + x => 0 * 3 + 0 => 0. その後、実際の読み取りを行うことができます。行全体を読みたい場合は、この計算を何度も行う必要があります。

代わりに、ギザギザの配列を見てください。メモリには次のように格納されています。

a: {0, 1, 2} b: {3, 4, 5} c: {6, 7, 8} {ref: a, ref:b, ref:c}

[0][0] にアクセスしたい場合、メモリ内のどこを読み取るのでしょうか? まず、配列 [0] への参照を取得しましょう。次に、セル [0] の内容を取得します。終わり。行全体を読みたい場合は、ポインタを 1 だけインクリメントする必要があります。

1 行だけではなく「配列」全体を反復処理する場合でも、ギザギザの配列と同じパフォーマンス上の利点があります。

ただし、例外が 1 つあります。列を反復することです。アクセスごとに比較的高価なメモリ読み取りを行うため、これはジャグ配列にとって非常に悪いことです。良くない。

それが問題だと感じる場合は、1 つの方法が残っています: 1 次元配列です! この場合、多次元配列 (y * rowLength + x) の背後にある理論を使用し、非常に単純な数学を使用します。行を反復するには: 1 ずつインクリメントします。列を反復するには、rowLength だけインクリメントします。

于 2010-10-19T00:33:12.410 に答える
1

多次元配列を持つ配列オブジェクトは 1 つだけですが、ジャグ配列は複数の異なる配列オブジェクトのネストです。1 対 1 の対戦や抽出方法 (ラッパーを使用しない) はありません。

于 2010-10-18T23:38:11.517 に答える
0

行を指定できるようにする DictionaryTable オブジェクトの拡張メソッドを作成できますか?

public static class IntArrayExt
{
    public static int[] Row(this int[,] array, int row)
    {
        int[] newArray = new int[3];
        for (int i = 0; i < array.Length; i++)
        {
            newArray[i] = array[row, i];
        }
        return newArray;
    }
}

int[,] distanceTable = new int[3, 3];
distanceTable[0, 0] = 0;
distanceTable[1, 1] = 0;
distanceTable[2, 2] = 0;

distanceTable[0, 1] = 10;
distanceTable[0, 2] = 40;

distanceTable[1, 0] = 10;
distanceTable[1, 2] = 25;

distanceTable[2, 0] = 40;
distanceTable[2, 1] = 25;

int[] twos = distanceTable.Row(2);

列を取得したい場合は、別の拡張メソッドを作成できます。

于 2010-10-18T23:50:21.347 に答える