سؤال

عند استعراض أحيانا تواجه هذا النوع من حلقة:

i = begin
while ( i != end ) {    
   // ... do stuff
   if ( i == end-1 (the one-but-last element) ) {
      ... do other stuff
   }
   increment i
}

ثم أنا أسأل هذا السؤال:هل أنت من كتبت هذا ؟

i = begin
mid = ( end - begin ) / 2 // (the middle element)
while ( i != end ) {    
   // ... do stuff
   if ( i > mid ) {
      ... do other stuff
   }
   increment i
}

في رأيي هذا يدق القصد من كتابة الحلقة:الحلقة لأن هناك شيء مشترك ينبغي القيام به من أجل كل عنصر من العناصر.باستخدام هذا بناء على بعض العناصر تفعل شيئا مختلفا.لذا نستنتج تحتاج حلقة منفصلة عن تلك العناصر:

i = begin
mid = ( end - begin ) / 2 //(the middle element)
while ( i != mid ) {    
   // ... do stuff
   increment i
}

while ( i != end ) {
   // ... do stuff
   // ... do other stuff
   increment i
}

الآن أنا حتى رأيت السؤال حتى على كيفية كتابة if-شرط في طريقة لطيفة...وحصلت حزين:شيئا ما ليس صحيحا هنا.

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

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

المحلول

@xtofl,

أنا أتفق مع القلق الخاص بك.

مليون مرة واجهت مشكلة مماثلة.

إما المطور يضيف معالجة خاصة أول أو آخر عنصر.

في معظم الحالات فإنه يستحق أن مجرد حلقة من startIdx + 1 أو endIdx - 1 عنصر أو حتى تقسيم واحد حلقة طويلة إلى عدة أقصر الحلقات.

في حالات نادرة جدا لا يمكن تقسيم الحلقة.

في رأيي من غير المألوف أشياء يجب أن يتم التعامل معها خارج حلقة كلما كان ذلك ممكنا.

نصائح أخرى

أنا لا أعتقد أن هذا السؤال يجب أن يجيب عليها مبدأ (مثلا ، "في حلقة علاج كل عنصر على قدم المساواة").بدلا من ذلك, يمكنك إلقاء نظرة على اثنين من العوامل لتقييم ما إذا كان التنفيذ هو جيدة أو سيئة:

  1. وقت الفعالية - هل التعليمات البرمجية المترجمة تشغيل سريع ، أو سيكون أسرع تفعله بشكل مختلف ؟
  2. رمز الصيانة - هل من السهل (آخر المطور) لفهم ما يحدث هنا ؟

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

إذا كان هو أسرع و أقل بصورة مقروءة ، أو أبطأ ولكن أكثر قابلية للقراءة ، لمعرفة أي العوامل أكثر أهمية في حالة محددة ، ومن ثم تقرر كيفية حلقة (أو حلقة).

وأنا أعلم أنني قد رأيت هذا عندما حاول الناس للانضمام عناصر المصفوفة إلى سلسلة مفصولة بفواصل:

for(i=0;i<elements.size;i++) {
   if (i>0) {
     string += ','
   }
   string += elements[i]
}

واما أن يكون أنه إذا شرط في هناك، أو كان لديك لتكرار سلسلة + = الخط مرة أخرى في نهاية المطاف.

والحل واضح في هذه الحالة هو

string = elements.join(',')

ولكن الانضمام الطريقة لا الحلقة نفسها داخليا. وليس هناك دائما طريقة لتفعل ما تريد.

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

في المقتطف الأخير الذي نشر، كنت تكرار رمز ل// .... تفعل الاشياء.

فمن المنطقي للحفاظ 2 الحلقات عندما يكون لديك مجموعة مختلفة تماما من العمليات على مجموعة مختلفة من المؤشرات.

i = begin
mid = ( end - begin ) / 2 //(the middle element)
while ( i != mid ) {    
   // ... do stuff
   increment i
}

while ( i != end ) {
   // ... do other stuff
   increment i
}

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

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

على سبيل المثال:

if(items == null)
    return null;

StringBuilder result = new StringBuilder();
if(items.Length != 0)
{
    result.Append(items[0]); // Special case outside loop.
    for(int i = 1; i < items.Length; i++) // Note: we start at element one.
    {
        result.Append(";");
        result.Append(items[i]);
    }
}
return result.ToString();

و وسط حالة وصفت عادي فقط سيئة.تخيل لو أن رمز ينمو ويحتاج إلى بتعميل الترميز في أساليب مختلفة.

إلا إذا كنت XML <grin> الحلقات يجب أن تبقى بسيطة ومختصرة قدر الإمكان.

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

وإذا كان هناك الكثير من الحالات الخاصة على الرغم من أنك يجب أن نفكر ربما عن الخروج مع بعض طريقة للتعامل مع مجموعتين مختلفتين من العناصر في بنيات منفصلة.

أنا أفضل أن مجرد استبعاد عنصر من حلقة وإعطاء spearate العلاج خارج حلقة

على سبيل المثال:يتيح النظر في القضية من EOF

i = begin
while ( i != end -1 ) {    
   // ... do stuff for element from begn to second last element
   increment i
}

if(given_array(end -1) != ''){
   // do stuff for the EOF element in the array
}

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

وشيء آخر أنا أكره أن أرى هو مقابل حالة نمط :

for (i=0; i<5; i++)
{
  switch(i)
  {
    case 0:
      // something
      break;
    case 1:
      // something else
      break;
    // etc...
  }
}

ولقد رأيت هذا في التعليمات البرمجية الحقيقي.

وأي واحد أداء أفضل؟

وإذا كان عدد من البنود كبيرة جدا ثم أود دائما حلقة مرة واحدة، وخاصة إذا كنت تسير على أداء <م> بعض العملية على كل بند. تكلفة تقييم مشروطة من المرجح أن تكون أقل من حلقات مرتين.

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

وينبغي أن يتم الحالة الخاصة خارج الحلقة إذا كان فقط ليتم تنفيذها مرة واحدة.

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

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

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