كيف يتم الاحتفاظ بعدد "الأشياء المنجزة" في خوارزمية متكررة في Java؟

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

سؤال

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

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

هل هناك طريقة للحصول على شيء مشابه للعمل لا يلوث الكود الخاص بي؟

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

المحلول

نظرًا لأنك اكتشفت بالفعل "اختراق" الأعداد الصحيحة القابلة للتغيير، فماذا عن هذا الخيار:

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

نصائح أخرى

إنه نوع من الاختراق، لكن في بعض الأحيان أستخدم AtomicInteger، وهو قابل للتغيير، للقيام بأشياء مثل هذه.لقد رأيت أيضًا حالات تم فيها تمرير int[] بالحجم 1.

الحل الحالي الذي أستخدمه هو:

int[] counter = {0};

ثم قم بتمريرها إلى الخوارزمية العودية:

public List<Thing> doIt (String aString, int[] counter) { ... }

وعندما أريد زيادتها:

counter[0]++;

ليست أنيقة للغاية، ولكنها تعمل...

الأعداد الصحيحة غير قابلة للتغيير، مما يعني أنه عند تمريرها كوسيطة فإنها تقوم بإنشاء نسخة بدلاً من مرجع لنفس العنصر.(توضيح).

للحصول على السلوك الذي تبحث عنه، يمكنك كتابة فصلك الخاص والذي يشبه عدد صحيح قابل للتغيير فقط.بعد ذلك، ما عليك سوى تمريرها إلى الدالة العودية، وستتم زيادتها داخل العودية، وعندما تصل إليها مرة أخرى بعد انتهاء العودية، ستظل محتفظة بقيمها الجديدة.

يحرر:لاحظ أن استخدام مصفوفة int[] هو شكل مختلف من هذه الطريقة...في Java، يتم تمرير المصفوفات أيضًا حسب المرجع بدلاً من نسخها مثل البدائيات أو الفئات غير القابلة للتغيير.

يمكنك فقط استخدام متغير فئة int ثابت يتم زيادته في كل مرة يتم فيها استدعاء طريقة doIt الخاصة بك.

يمكنك أيضًا القيام بما يلي:

private int recurse (int i) {

    if (someConditionkeepOnGoing) {
        i = recurse(i+1);
    }

    return i;
}

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

من المحتمل أن يؤدي هذا أيضًا إلى جعل الخوارزمية أسرع لأنها لا تحتاج إلى إجراء استدعاء دالة لكل حرف.

ما لم يكن هناك بالطبع سبب محدد لضرورة التكرار.

أحد الاحتمالات التي يمكنني التفكير فيها هو تخزين العدد في متغير عضو للفئة.وهذا بالطبع يفترض أن الجمهور doIt يتم استدعاء الطريقة فقط بواسطة مؤشر ترابط واحد.

هناك خيار آخر وهو إعادة هيكلة الطريقة العامة لاستدعاء طريقة المساعدة الخاصة.تأخذ الطريقة الخاصة القائمة كمعلمة وترجع العدد.على سبيل المثال:

public List<Thing> doIt(String aString) {
    List<Thing> list = new ArrayList<Thing>();
    int count = doItHelper(aString, list, 0);
    // ...
    return list;
}

private int doItHelper(String aString, List<Thing> list, int count) {
    // ...
    // do something that updates count
    count = doItHelper(aString, list, count);
    // ...
    return count;
}

يفترض هذا أنه يمكنك القيام بمعالجة الأخطاء بشكل عام doIt الطريقة، منذ count لا يتم تمرير المتغير فعليًا إلى المتصل.إذا كنت بحاجة إلى القيام بذلك، فيمكنك بالطبع طرح استثناء:

public List<Thing> doIt(String aString) throws SomeCustomException {
    List<Thing> list = new ArrayList<Thing>();
    int count = doItHelper(aString, list, 0);
    // ...
    if (someErrorOccurred) {
        throw new SomeCustomException("Error occurred at chracter index " + count, count);
    }
    return list;
}

من الصعب معرفة ما إذا كان ذلك سيساعد دون معرفة المزيد حول كيفية عمل الخوارزمية فعليًا.

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