متجه تهيئة المتجه
-
29-09-2019 - |
سؤال
أواجه صعوبة في الحصول على رأسي حول كيفية تهيئة متجه المتجهات.
Typedef Vector <Vector <Vector <Vector <Float>>> DataContainer ؛
أريد أن يتوافق هذا
level_1 (2 elements/vectors)
level_2 (7 elements/vectors)
level_3 (480 elements/vectors)
level_4 (31 elements of float)
معالجة العناصر ليست هي المشكلة. يجب أن يكون هذا بسيطًا مثل شيء مثل
dc[0][1][2][3];
المشكلة هي أنني بحاجة إلى ملء البيانات التي تخرج من طلب من ملف بحيث يجب وضع العناصر المتتالية شيئًا مثل
dc[0][3][230][22];
dc[1][3][110][6]; //...etc
لذلك أحتاج إلى تهيئة V من V مسبقًا.
هل أنا أخرج نفسي أم أن هذا بسيط مثل
for 0..1
for 0..6
for 0..479
for 0..30
dc[i][j][k][l] = 0.0;
لا يبدو أن هذا يجب أن يعمل. بطريقة ما ، يجب تهيئة متجهات المستوى الأعلى أولاً.
أي مساعدة موضع تقدير. أنا متأكد من أن هذا يجب أن يكون أبسط مما أتخيله.
المحلول
لو سمحت لا تستخدم المتجهات المتداخلة إذا حجم التخزين الخاص بك معروف في وقت مبكر, ، أي هناك أ سبب محدد لماذا على سبيل المثال ، يجب أن يكون الحجم 6 ، ولن يتغير أبدًا. فقط استخدم صفيف عادي. الأفضل من ذلك ، الاستخدام
boost::array
. وبهذه الطريقة ، تحصل على جميع فوائد وجود صفيف عادي (وفر كميات هائلة من المساحة عندما تذهب متعدد الأبعاد) ، وفوائد وجود مثيل حقيقي للكائن.لو سمحت لا تستخدم المتجهات المتداخلة إذا كان يجب أن يكون التخزين الخاص بك مستطيلي, ، أي يمكنك تغيير حجم واحد أو أكثر من الأبعاد ، ولكن يجب أن يكون كل "صف" نفس الطول في مرحلة ما. يستخدم
boost::multi_array
. وبهذه الطريقة ، يمكنك توثيق "هذا التخزين مستطيل" ، وتوفير كميات هائلة من المساحة ولا تزال تحصل على القدرة على تغيير الحجم ، وفوائد وجود كائن حقيقي ، وما إلى ذلك.
الشيء عن std::vector
هل من المفترض أن تكون (أ) قابلة للإصلاح و (ب) لا تهتم بمحتوياتها في أدنى ، طالما أنها من النوع الصحيح. هذا يعني أنه إذا كان لديك vector<vector<int> >
, ، ثم يجب على جميع "متجهات الصف" الحفاظ على معلوماتها المنفصلة في حفظ الدفاتر حول المدة التي تستغرقها - حتى لو كنت ترغب في إنفاذ أنها بنفس الطول. وهذا يعني أيضًا أنهم جميعًا يديرون تخصيصات ذاكرة منفصلة ، والتي تؤذي الأداء (سلوك ذاكرة التخزين المؤقت) ، وتضيع مساحة أكبر بسبب كيفية std::vector
إعادة تخصيص. boost::multi_array
تم تصميمه مع توقع أنك قد ترغب في تغيير حجمه ، ولكن لن يتم تغيير حجمه باستمرار عن طريق الإلحاق (الصفوف ، لصفيف / وجوه ثنائية الأبعاد ، لمجموعة / صفيف ثلاثي الأبعاد إلى النهاية. std::vector
تم تصميمه إلى مساحة نفايات (يحتمل) للتأكد من أن العملية ليست بطيئة. boost::multi_array
تم تصميمه لتوفير المساحة والحفاظ على كل شيء منظم بدقة في الذاكرة.
هكذا قال:
نعم ، تحتاج إلى القيام بشيء ما قبل أن تتمكن من الفهرس في المتجه. std::vector
لن تتسبب بطريقة سحرية في ظهور الفهارس في حياته لأنك تريد تخزين شيء هناك. ومع ذلك ، من السهل التعامل مع:
يمكنك تقصير المتجه مع الكمية المناسبة من الأصفار أولاً ، ثم استبدالها ، باستخدام (size_t n, const T& value = T())
البناء. هذا هو،
std::vector<int> foo(10); // makes a vector of 10 ints, each of which is 0
لأن "البناء الافتراضي" int لديه القيمة 0.
في حالتك ، نحتاج إلى تحديد حجم كل بُعد ، من خلال إنشاء محلات فرعية من الحجم المناسب والسماح للمركبة بنسخها. هذا يبدو مثل:
typedef vector<float> d1;
typedef vector<d1> d2;
typedef vector<d2> d3;
typedef vector<d3> d4;
d4 result(2, d3(7, d2(480, d1(31))));
هذا هو ، لم يكشف عن اسمه d1
تم إنشاؤه من الحجم 31 ، والذي يستخدم لتهيئة الافتراضي d2
, ، والذي يستخدم لتهيئة الافتراضي d3
, ، الذي يستخدم للتهيئة result
.
هناك مناهج أخرى ، لكنها أكثر جاذبية إذا كنت تريد فقط أن تبدأ مجموعة من الأصفار. إذا كنت ستقرأ مجموعة البيانات بأكملها من ملف ، على الرغم من ذلك:
يمكنك استخدام
.push_back()
لإلحاق المتجه. اجعل فارغًاd1
قبل حلقة داخلية أكثر ، والتي تشرقها مرارًا وتكرارًا.push_back()
لملئه. فقط بعد الحلقة ، أنت.push_back()
النتيجة علىd2
الذي أنشأته قبل حلقة الخمر التالية مباشرة ، وهلم جرا.يمكنك تغيير حجم المتجه مسبقًا مع
.resize()
, ، ثم الفهرس فيه بشكل طبيعي (حتى المبلغ الذي قمت بتغيير حجمه).
نصائح أخرى
من المحتمل أن تضطر إلى ضبط حجم أو ذاكرة الاحتياط
هل يمكن أن تفعل ذلك من أجل ذلك أو متداخل لذلك من شأنه أن يتصل
myVector.resize(x); //or size
على كل مستوى.
تحرير: أعترف أن هذا الرمز ليس أنيقًا. أنا أحب @karl الإجابة وهي الطريقة الصحيحة للذهاب.
يتم تجميع هذا الرمز واختباره. طبعت 208320 الأصفار المتوقع (2 * 7 * 480 * 31)
#include <iostream>
#include <vector>
using namespace std;
typedef vector< vector < vector < vector< float > > > > DataContainer;
int main()
{
const int LEVEL1_SIZE = 2;
const int LEVEL2_SIZE = 7;
const int LEVEL3_SIZE = 480;
const int LEVEL4_SIZE = 31;
DataContainer dc;
dc.resize(LEVEL1_SIZE);
for (int i = 0; i < LEVEL1_SIZE; ++i) {
dc[i].resize(LEVEL2_SIZE);
for (int j = 0; j < LEVEL2_SIZE; ++j) {
dc[i][j].resize(LEVEL3_SIZE);
for (int k = 0; k < LEVEL3_SIZE; ++k) {
dc[i][j][k].resize(LEVEL4_SIZE);
}
}
}
for (int i = 0; i < LEVEL1_SIZE; ++i) {
for (int j = 0; j < LEVEL2_SIZE; ++j) {
for (int k = 0; k < LEVEL3_SIZE; ++k) {
for (int l = 0; l < LEVEL4_SIZE; ++l) {
dc[i][j][k][l] = 0.0;
}
}
}
}
for (int i = 0; i < LEVEL1_SIZE; ++i) {
for (int j = 0; j < LEVEL2_SIZE; ++j) {
for (int k = 0; k < LEVEL3_SIZE; ++k) {
for (int l = 0; l < LEVEL4_SIZE; ++l) {
cout << dc[i][j][k][l] << " ";
}
}
}
}
cout << endl;
return 0;
}