من الممكن تحويل مصفوفة C# double[,,] إلى double[] بدون عمل نسخة

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

  •  01-07-2019
  •  | 
  •  

سؤال

لدي مصفوفات ضخمة ثلاثية الأبعاد من الأرقام في تطبيق .NET الخاص بي.أحتاج إلى تحويلها إلى مصفوفة أحادية الأبعاد لتمريرها إلى مكتبة COM.هل هناك طريقة لتحويل المصفوفة دون عمل نسخة من جميع البيانات؟

يمكنني إجراء التحويل بهذه الطريقة، ولكن بعد ذلك أستخدم ضعف كمية الذاكرة التي تمثل مشكلة في تطبيقي:

  double[] result = new double[input.GetLength(0) * input.GetLength(1) * input.GetLength(2)];
  for (i = 0; i < input.GetLength(0); i++) 
    for (j = 0; j < input.GetLength(1); j++) 
      for (k = 0; k < input.GetLength(2); k++) 
        result[i * input.GetLength(1) * input.GetLength(2) + j * input.GetLength(2) + k)] = input[i,j,l];
  return result;
هل كانت مفيدة؟

المحلول

لا أعتقد أن الطريقة التي تخزن بها لغة C# تلك البيانات في الذاكرة ستجعلها ممكنة بنفس الطريقة التي قد تكون بها عملية بسيطة في لغة C.لماذا لا تستخدم مصفوفة 1d لتبدأ وربما تنشئ فئة للنوع حتى تتمكن من الوصول إليه في برنامجك كما لو كان مصفوفة ثلاثية الأبعاد؟

نصائح أخرى

لسوء الحظ، لا يُضمن وجود مصفوفات C# في ذاكرة متجاورة كما هو الحال في اللغات الأقرب إلى المعدن مثل C.لذا، لا.لا توجد طريقة لتحويل double[,,] إلى double[] بدون نسخة عنصر بعنصر.

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

بالطبع، يضيف هذا المستوى الإضافي من التجريد تعقيدًا وعملًا خاصًا به، ولكنه سيسمح لك بإجراء الحد الأدنى من التغييرات على التعليمات البرمجية الموجودة التي تستخدم كائنات مزدوجة[،،]، بينما يسمح لك باستخدام مصفوفة مزدوجة[] واحدة لكليهما التشغيل المتداخل وحسابك في C#.

class Matrix3
{
    // referece-to-element object
    public struct Matrix3Elem{
        private Matrix3Impl impl;
        private uint dim0, dim1, dim2;
        // other constructors
        Matrix3Elem(Matrix3Impl impl_, uint dim0_, uint dim1_, uint dim2_) {
            impl = impl_; dim0 = dim0_; dim1 = dim1_; dim2 = dim2_;
        }
        public double Value{
            get { return impl.GetAt(dim0,dim1,dim2); }
            set { impl.SetAt(dim0, dim1, dim2, value); }
        }
    }

    // implementation object
    internal class Matrix3Impl
    {
        private double[] data;
        uint dsize0, dsize1, dsize2; // dimension sizes
        // .. Resize() 
        public double GetAt(uint dim0, uint dim1, uint dim2) {
            // .. check bounds
            return data[ (dim2 * dsize1 + dim1) * dsize0 + dim0 ];
        }
        public void SetAt(uint dim0, uint dim1, uint dim2, double value) {
            // .. check bounds
            data[ (dim2 * dsize1 + dim1) * dsize0 + dim0 ] = value;
        }
    }

    private Matrix3Impl impl;

    public Matrix3Elem Elem(uint dim0, uint dim1, uint dim2){
        return new Matrix2Elem(dim0, dim1, dim2);
    }
    // .. Resize
    // .. GetLength0(), GetLength1(), GetLength1()
}

ومن ثم استخدام هذا النوع للقراءة والكتابة - تتم كتابة "foo[1,2,3]" الآن كـ "foo.Elem(1,2,3).Value"، في كل من قيم القراءة وقيم الكتابة، في الجانب الأيسر من المهمة وتعبيرات القيمة.

void normalize(Matrix3 m){

    double s = 0;
    for (i = 0; i < input.GetLength0; i++)     
        for (j = 0; j < input.GetLength(1); j++)       
            for (k = 0; k < input.GetLength(2); k++)
    {
        s += m.Elem(i,j,k).Value;
    }
    for (i = 0; i < input.GetLength0; i++)     
        for (j = 0; j < input.GetLength(1); j++)       
            for (k = 0; k < input.GetLength(2); k++)
    {
        m.Elem(i,j,k).Value /= s;
    }
}

مرة أخرى، تتم إضافة تكاليف التطوير، ولكن يتم مشاركة البيانات، وإزالة تكاليف النسخ العامة ونسخ تكاليف التطوير ذات الصلة.إنها مقايضة.

كحل بديل، يمكنك إنشاء فئة تحافظ على المصفوفة في شكل أحادي الأبعاد (ربما حتى في شكل أقرب إلى الشكل المعدني حتى تتمكن من تمريرها بسهولة إلى مكتبة COM؟) ثم قم بتحميل عامل التشغيل [] على هذه الفئة لجعلها قابلة للاستخدام كمصفوفة متعددة الأبعاد في كود C# الخاص بك.

بدون معرفة تفاصيل مكتبة COM الخاصة بك، سأفكر في إنشاء فئة واجهة في .Net وتعريضها لـ COM، إذا لزم الأمر.
ستتطلب الواجهة الخاصة بك مزدوجًا[،،] وتحتوي على مفهرس يقوم بالتخطيط من [] إلى [،،].

يحرر:أوافق على النقاط الواردة في التعليقات، واقتراح لورين هو الأفضل.

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