php - لغة - كيفية تحديد التكرار الأول والأخير في حلقة foreach؟




حلقة for المتداخلة (12)

السؤال بسيط. لدي حلقة foreach في الكود:

foreach($array as $element) {
    //code
}

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

كيف نفعل ذلك؟


1: لماذا لا تستخدم بسيطة لبيان؟ إذا افترضنا أنك تستخدم مصفوفة حقيقية وليس Iterator فيمكنك بسهولة التحقق مما إذا كان متغير العداد 0 أو أقل من العدد الكلي للعناصر. في رأيي هذا هو الحل الأكثر نظيفة ومفهومة ...

$array = array( ... );

$count = count( $array );

for ( $i = 0; $i < $count; $i++ )
{

    $current = $array[ $i ];

    if ( $i == 0 )
    {

        // process first element

    }

    if ( $i == $count - 1 )
    {

        // process last element

    }

}

2: يجب أن تفكر في استخدام مجموعات متداخلة لتخزين بنية شجارك. بالإضافة إلى ذلك ، يمكنك تحسين كل شيء باستخدام وظائف متكررة.


إذا كان الصفيف الخاص بك يحتوي على قيم صفيف فريد ، فإن تحديد العنصر الأول والأخير هو أمر بسيط:

foreach($array as $element) {
    if ($element === reset($array))
        echo 'FIRST ELEMENT!';

    if ($element === end($array))
        echo 'LAST ELEMENT!';
}

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

foreach($array as $key => $element) {
    reset($array);
    if ($key === key($array))
        echo 'FIRST ELEMENT!';

    end($array);
    if ($key === key($array))
        echo 'LAST ELEMENT!';
}

تحديث: بعض الأشخاص قلقون بشأن الأداء و / أو تعديل مؤشر الصفيف داخل حلقة foreach. لتلك ، يمكنك تخزين قيمة المفتاح قبل الحلقة.

reset($array);
$first = key($array);
foreach($array as $key => $element) {
    if ($key === $first)
        echo 'FIRST ELEMENT!';
}

افضل جواب:

$arr = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

foreach ($arr as $a) {

// This is the line that does the checking
if (!each($arr)) echo "End!\n";

echo $a."\n";

}

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

يستخدم الحل المتعارف عليه حاليًا حلقة وشيكًا داخل الحلقة التي سيتم إجراؤها every_single_iteration ، والطريقة الصحيحة (السريعة) للقيام بذلك هي كالتالي:

$numItems = count($arr);
$i=0;
$firstitem=$arr[0];
$i++;
while($i<$numItems-1){
    $some_item=$arr[$i];
    $i++;
}
$last_item=$arr[$i];
$i++;

أظهر مقياس صغير محلية الصنع ما يلي:

test1: 100000 يدير نموذج مورغ

الوقت: 1869.3430423737 ميلي ثانية

test2: 100000 يدير النموذج إذا كان الماضي

الوقت: 3235.6359958649 ميلي ثانية

ومن الواضح تمامًا أن الشيكات تكلف الكثير ، وبالطبع يزداد الأمر سوءًا كلما زادت الفحوصات المتغيرة التي تضيفها ؛)


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

$firstElement = true;

foreach ($reportData->result() as $row) 
{
       if($firstElement) { echo "first element"; $firstElement=false; }
       // Other lines of codes here
}

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


جرب هذا:

function children( &$parents, $parent, $selected ){
  if ($parents[$parent]){
    $list = '<ul>';
    $counter = count($parents[$parent]);
    $class = array('first');
    foreach ($parents[$parent] as $child){
      if ($child['id'] == $selected)  $class[] = 'active';
      if (!--$counter) $class[] = 'last';
      $list .= '<li class="' . implode(' ', $class) . '"><div><a href="]?id=' . $child['id'] . '" alt="' . $child['name'] . '">' . $child['name'] . '</a></div></li>';
      $class = array();
      $list .= children($parents, $child['id'], $selected);
    }
    $list .= '</ul>';
    return $list;
  }
}
$output .= children( $parents, 0, $p_industry_id);

للعثور على العنصر الأخير ، أجد أن جزء الرمز هذا يعمل في كل مرة:

foreach( $items as $item ) {
    if( !next( $items ) ) {
        echo 'Last Item';
    }
}

محاولة للعثور على الأول ستكون:

$first = true; 
foreach ( $obj as $value )
{
  if ( $first )
  {
    // do something
    $first = false; //in order not to get into the if statement for the next loops
  }
  else
  {
    // do something else for all loops except the first
  }
}

نسخة مبسطة أكثر مما سبق ويفترض أنك لا تستخدم فهارس مخصصة ...

$len = count($array);
foreach ($array as $index => $item) {
    if ($index == 0) {
        // first
    } else if ($index == $len - 1) {
        // last
    }
}

الإصدار 2 - لأنني جئت إلى استنزاف استخدام آخر ما لم يكن ضروريا.

$len = count($array);
foreach ($array as $index => $item) {
    if ($index == 0) {
        // first
        // do something
        continue;
    }

    if ($index == $len - 1) {
        // last
        // do something
        continue;
    }
}

يمكنك إزالة العناصر الأولى والأخيرة من الصفيف ومعالجتها بشكل منفصل.
مثله:

<?php
$array = something();
$first = array_shift($array);
$last = array_pop($array);

// do something with $first
foreach ($array as $item) {
 // do something with $item
}
// do something with $last
?>

ستؤدي إزالة كل التنسيق إلى CSS بدلاً من العلامات المضمّنة إلى تحسين الشفرة وتسريع وقت التحميل.

يمكنك أيضًا تجنب خلط HTML مع منطق php كلما أمكن ذلك.
يمكن جعل صفحتك أكثر قابلية للقراءة وصلاحية من خلال فصل أشياء كهذه:

<?php
function create_menu($params) {
  //retirive menu items 
  //get collection 
  $collection = get('xxcollection') ;
  foreach($collection as $c) show_collection($c);
}

function show_subcat($val) {
  ?>
    <div class="sub_node" style="display:none">
      <img src="../images/dtree/join.gif" align="absmiddle" style="padding-left:2px;" />
      <a id="'.$val['xsubcatid'].'" href="javascript:void(0)" onclick="getProduct(this , event)" class="sub_node_links"  >
        <?php echo $val['xsubcatname']; ?>
      </a>
    </div>
  <?php
}

function show_cat($item) {
  ?>
    <div class="node" >
      <img src="../images/dtree/plus.gif" align="absmiddle" class="node_item" id="plus" />
      <img src="../images/dtree/folder.gif" align="absmiddle" id="folder">
      <?php echo $item['xcatname']; ?>
      <?php 
        $subcat = get_where('xxsubcategory' , array('xcatid'=>$item['xcatid'])) ;
        foreach($subcat as $val) show_subcat($val);
      ?>
    </div>
  <?php
}

function show_collection($c) {
  ?>
    <div class="parent" style="direction:rtl">
      <img src="../images/dtree/minus.gif" align="absmiddle" class="parent_item" id="minus" />
      <img src="../images/dtree/base.gif" align="absmiddle" id="base">
      <?php echo $c['xcollectionname']; ?>
      <?php
        //get categories 
        $cat = get_where('xxcategory' , array('xcollectionid'=>$c['xcollectionid']));
        foreach($cat as $item) show_cat($item);
      ?>
    </div>
  <?php
}
?>

يمكنك استخدام عداد:

$i = 0;
$len = count($array);
foreach ($array as $item) {
    if ($i == 0) {
        // first
    } else if ($i == $len - 1) {
        // last
    }
    // …
    $i++;
}

يمكنك استخدام وظيفة مجهولة أيضًا:

$indexOfLastElement = count($array) - 1;
array_walk($array, function($element, $index) use ($indexOfLastElement) {
    // do something
    if (0 === $index) {
        // first element‘s treatment
    }
    if ($indexOfLastElement === $index) {
        // last not least
    }
});

يجب ذكر ثلاثة أشياء أخرى:

  • إذا لم تتم فهرسة صفيفك بشكل صارم (رقميًا) ، يجب عليك توجيه الصفيف من خلال array_values أولاً.
  • إذا كنت بحاجة إلى تعديل $element يجب عليك تمريره بالرجوع إليه ( &$element ).
  • أي متغيرات من خارج الوظيفة المجهولة التي تحتاجها في الداخل ، سيكون عليك $indexOfLastElement بجوار $indexOfLastElement داخل $indexOfLastElement use ، مرة أخرى بالرجوع إذا لزم الأمر.




foreach