كيف يمكنك تهيئة مصفوفة ثنائية الأبعاد عندما لا تعرف حجمها؟

StackOverflow https://stackoverflow.com/questions/50558

  •  09-06-2019
  •  | 
  •  

سؤال

لدي مصفوفة ثنائية الأبعاد أحتاج إلى تحميل البيانات فيها.أعرف عرض البيانات (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[,];

أحصل على "إنشاء صفيف يجب أن يكون له حجم صفيف أو مُهيئ صفيف."

شكرا لك ، كيث

هل كانت مفيدة؟

المحلول

لا يمكنك استخدام مصفوفة.أو بالأحرى، ستحتاج إلى اختيار حجم، وإذا انتهى بك الأمر إلى الحاجة إلى المزيد، فسيتعين عليك تخصيص مصفوفة جديدة أكبر ونسخ البيانات من القديم إلى الجديد، والاستمرار كما كان من قبل (حتى لقد تجاوزت حجم الجديد ...)

بشكل عام، يمكنك اختيار إحدى فئات المجموعة - ArrayList، List<>، LinkedList<>، وما إلى ذلك.- أيهما يعتمد كثيرًا على ما تبحث عنه؛ستمنحك القائمة أقرب شيء لما وصفته في البداية، بينما سيتجنب 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]

أوه، ومن الجدير بالذكر (كما جراوينولف فعلت)، أن ما أفعله هنا لا يمنحك نفس بنية الذاكرة مثل مجموعة واحدة متعددة الأبعاد - تحت الغطاء، إنها مجموعة من المراجع إلى صفائف أخرى تحتوي بالفعل على البيانات.يؤدي هذا إلى تسريع بناء المصفوفة بشكل كبير من خلال جعل عملية إعادة التخصيص أرخص، ولكن يمكن أن يكون لها تأثير على سرعة الوصول (وبالطبع، استخدام الذاكرة).يعتمد ما إذا كانت هذه مشكلة بالنسبة لك كثيرًا على ما ستفعله بالبيانات بعد تحميلها...وهل هناك مائتي سجل أو مليوني سجل.

نصائح أخرى

لا يمكنك إنشاء مصفوفة في .NET (بدلاً من الإعلان عن مرجع لها، وهو ما فعلته في المثال الخاص بك) دون تحديد أبعادها، سواء بشكل صريح أو ضمني عن طريق تحديد مجموعة من القيم الحرفية عند تهيئتها .(على سبيل المثالint[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };)

تحتاج إلى استخدام بنية بيانات ذات حجم متغير أولاً (ستكون القائمة العامة المكونة من 22 عنصرًا من المصفوفات 1-d هي الأبسط) ثم تخصيص المصفوفة الخاصة بك ونسخ بياناتك إليها بعد الانتهاء من القراءة ومعرفة عدد الصفوف انت تحتاج.

أود فقط استخدام قائمة، ثم تحويل تلك القائمة إلى مصفوفة.

ستلاحظ هنا أنني استخدمت مصفوفة خشنة (تعويم[]]) بدلاً من مصفوفة مربعة (تعويم [،]).وإلى جانب كونها الطريقة "القياسية" للقيام بالأشياء، ينبغي أن تكون أسرع بكثير.عند تحويل البيانات من قائمة إلى مصفوفة، ما عليك سوى نسخ مؤشرات [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();

أستخدم عمومًا المجموعات الأفضل لهذا النوع من العمل (List، ArrayList وما إلى ذلك) ثم (إذا لزم الأمر حقًا) ألقيها على T[,] عندما أنتهي.

ستحتاج إما إلى تخصيص المصفوفة مسبقًا إلى الحد الأقصى للحجم (float[999,22] ) أو استخدام بنية بيانات مختلفة.

أعتقد أنه يمكنك النسخ/تغيير الحجم بسرعة..(لكنني لا أعتقد أنك تريد ذلك)

أعتقد أن القائمة تبدو معقولة.

يمكنك أيضًا استخدام قائمة ArrayList ثنائية الأبعاد (من System.Collections) - حيث تقوم بإنشاء قائمة ArrayList، ثم تضع قائمة ArrayList أخرى بداخلها.سيمنحك هذا تغيير الحجم الديناميكي الذي تحتاجه، ولكن على حساب القليل من النفقات العامة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top