8

データをロードする必要がある 2 次元配列があります。データの幅 (22 個の値) はわかっていますが、高さはわかりません (約 4000 レコードと推定されますが、可変です)。

次のように宣言しています。

float[,] _calibrationSet;
    ....
int calibrationRow = 0;
While (recordsToRead)
{
  for (int i = 0; i < SensorCount; i++)
   {
     _calibrationSet[calibrationRow, i] = calibrationArrayView.ReadFloat();
   }
   calibrationRow++;
}

これにより NullReferenceException が発生するため、次のように初期化しようとすると:

_calibrationSet = new float[,];

「配列の作成には配列サイズまたは配列初期化子が必要です」というメッセージが表示されます。

ありがとう、キース

4

6 に答える 6

8

配列は使用できません。むしろ、サイズを選択する必要があり、それ以上のサイズが必要になった場合は、新しい、より大きな配列を割り当て、古い配列から新しい配列にデータをコピーし、以前と同じように (まで) 続行する必要があります。あなたは新しいもののサイズを超えています...)

通常、ArrayList、List<>、LinkedList<> などのコレクション クラスのいずれかを使用します。どのクラスを使用するかは、探しているものに大きく依存します。List は最初に説明したものに最も近いものを提供しますが、LinkedList<> は頻繁な再割り当ての問題を回避します (アクセスが遅くなり、メモリ使用量が増えるという犠牲を払って)。

例:

List<float[]> _calibrationSet = new List<float[]>();

// ...

while (recordsToRead)
{
    float[] record = new float[SensorCount];
    for (int i = 0; i < SensorCount; i++)
    {
        record[i] = calibrationArrayView.ReadFloat();
    }
    _calibrationSet.Add(record);
}

// access later: _calibrationSet[record][sensor]

ああ、注目に値するのは ( Grauenwolfが行ったように)、ここで私が行っていることは、単一の多次元配列と同じメモリ構造を提供しないということです。内部的には、それは他の配列への参照の配列です。実際にデータを保持します。これにより、再割り当てが安価になり、配列の構築が大幅に高速化されますが、アクセス速度 (そしてもちろんメモリ使用量) に影響を与える可能性があります。これが問題になるかどうかは、データがロードされた後にデータをどうするか、および 200 レコードか 200 万レコードかによって大きく異なります。

于 2008-09-08T20:23:58.133 に答える
2

.NET で配列を作成することはできません (配列への参照を宣言するのとは対照的に、これはあなたの例で行ったことです)。 . (例: int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };)

最初に可変サイズのデータ​​構造を使用する必要があります (22 要素の 1 次元配列の一般的なリストが最も簡単です)。次に、配列を割り当てて、読み取りが終了し、行数がわかった後にデータをそこにコピーします。あなたが必要です。

于 2008-09-08T20:24:20.677 に答える
1

リストを使用して、そのリストを配列に変換します。

ここで、正方配列 (float [,]) の代わりにギザギザ配列 (float[][]) を使用していることに気付くでしょう。物事を行う「標準的な」方法であることに加えて、はるかに高速である必要があります。データをリストから配列に変換するときは、[calibrationRow] ポインターをコピーするだけです。正方配列を使用すると、[calibrationRow] x [SensorCount] フロートをコピーする必要があります。

        var tempCalibrationSet = new List<float[]>();
        const int SensorCount = 22;
        int calibrationRow = 0;

        while (recordsToRead())
        {
            tempCalibrationSet[calibrationRow] = new float[SensorCount];

            for (int i = 0; i < SensorCount; i++)
            {
                tempCalibrationSet[calibrationRow][i] = calibrationArrayView.ReadFloat();
            } calibrationRow++;
        }

        float[][] _calibrationSet = tempCalibrationSet.ToArray();
于 2008-09-08T20:27:45.753 に答える
0

私は通常、この種の作業 (List、ArrayList など) にはより適切なコレクションを使用し、(本当に必要な場合) 完了したら T[,] にキャストします。

于 2008-09-08T20:25:19.363 に答える
0

配列を最大サイズ (float[999,22] ) に事前に割り当てるか、別のデータ構造を使用する必要があります。

その場でコピー/サイズ変更できると思います..(しかし、私はあなたがしたいとは思わない)

リストは合理的に聞こえると思います。

于 2008-09-08T20:26:46.520 に答える
0

(System.Collections から) 2 次元の ArrayList を使用することもできます。ArrayList を作成し、その中に別の ArrayList を配置します。これにより、必要な動的なサイズ変更が可能になりますが、多少のオーバーヘッドが発生します。

于 2008-09-08T20:28:34.347 に答える