คำถามง่าย ๆ ฉันมีforeach
วงวนในรหัสของฉัน:
foreach($array as $element) {
//code
}
ในวงนี้ฉันต้องการที่จะตอบสนองที่แตกต่างกันเมื่อเราอยู่ในการทำซ้ำครั้งแรกหรือครั้งสุดท้าย
ทำอย่างไร
คำถามง่าย ๆ ฉันมีforeach
วงวนในรหัสของฉัน:
foreach($array as $element) {
//code
}
ในวงนี้ฉันต้องการที่จะตอบสนองที่แตกต่างกันเมื่อเราอยู่ในการทำซ้ำครั้งแรกหรือครั้งสุดท้าย
ทำอย่างไร
คำตอบ:
คุณสามารถใช้เคาน์เตอร์:
$i = 0;
$len = count($array);
foreach ($array as $item) {
if ($i == 0) {
// first
} else if ($i == $len - 1) {
// last
}
// …
$i++;
}
$i = 1
คุณไม่ต้องกังวลเกี่ยวกับการใช้งานเพียงแค่$len - 1
$len
หากคุณต้องการโซลูชันที่ไม่ต้องการการเริ่มต้นของตัวนับนอกลูปฉันขอเสนอการเปรียบเทียบคีย์การวนซ้ำปัจจุบันกับฟังก์ชันที่บอกให้คุณทราบถึงคีย์สุดท้าย / แรกของอาร์เรย์
สิ่งนี้จะมีประสิทธิภาพมากขึ้น (และสามารถอ่านได้มากขึ้น) ด้วย PHP 7.3 ที่กำลังจะมาถึง
foreach($array as $key => $element) {
if ($key === array_key_first($array))
echo 'FIRST ELEMENT!';
if ($key === array_key_last($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!';
}
end()
+ key()
การวนซ้ำของลูป - ถ้ามันทั้งคู่นั่นคือ 4 วิธีที่ถูกเรียกทุกครั้ง จริงอยู่ที่การดำเนินการเหล่านี้มีน้ำหนักเบามากและอาจเป็นเพียงการค้นหาตัวชี้ แต่จากนั้นเอกสารจะดำเนินการเพื่อระบุreset()
และend()
แก้ไขตัวชี้ภายในของอาร์เรย์ - ดังนั้นจะเร็วกว่าตัวนับหรือไม่ อาจจะไม่
reset()
สายก่อนหน้า foreach และแคชผลลัพธ์$first
ได้
ในการค้นหารายการสุดท้ายฉันพบว่าโค้ดชิ้นนี้ใช้ได้ทุกครั้ง:
foreach( $items as $item ) {
if( !next( $items ) ) {
echo 'Last Item';
}
}
[true,true,false,true]
แต่ที่จะชี้แจงในการแก้ไขปัญหาที่คนอื่นจะชี้ให้เห็นว่ามันอย่างสม่ำเสมอจะล้มเหลวกับอาร์เรย์เช่น false
แต่ส่วนตัวผมจะใช้ทุกที่ทุกเวลานี้ฉันกำลังจัดการกับอาร์เรย์ที่ไม่ได้มีบูล
next()
ไม่ควรใช้ภายในลูป foreach มันเลอะตัวชี้อาร์เรย์ภายใน ตรวจสอบเอกสารสำหรับข้อมูลเพิ่มเติม
เวอร์ชันด้านบนที่ง่ายขึ้นและสันนิษฐานว่าคุณไม่ได้ใช้ดัชนีที่กำหนดเอง ...
$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;
}
}
if ($index == count($array) - 1)
โดยการทำ ดูที่นี่
คุณสามารถลบองค์ประกอบแรกและสุดท้ายออกจากอาร์เรย์และดำเนินการแยกต่างหาก
แบบนี้:
<?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) {
//retrieve 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
}
?>
ความพยายามที่จะหาคนแรกจะเป็น:
$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
}
}
แค่ใช้งานได้!
// Set the array pointer to the last key
end($array);
// Store the last key
$lastkey = key($array);
foreach($array as $key => $element) {
....do array stuff
if ($lastkey === key($array))
echo 'THE LAST ELEMENT! '.$array[$lastkey];
}
ขอบคุณ @billynoah สำหรับการแยกแยะปัญหาสุดท้าย
if ($key === $lastkey)
ฉันเพียงจะชี้แจง
if ($lastkey === $key)
?
PHP Warning: key() expects parameter 1 to be array, integer given in php shell code on line 1
key()
" ส่งคืนค่าขององค์ประกอบสุดท้าย " และคาดว่าอาร์เรย์จะเป็นอินพุต end()
end()
key()
1: ทำไมไม่ใช้for
คำสั่งง่าย ๆ? สมมติว่าคุณกำลังใช้อาร์เรย์จริงและไม่ใช่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: คุณควรพิจารณาใช้ชุดที่ซ้อนกันเพื่อจัดเก็บโครงสร้างต้นไม้ของคุณ นอกจากนี้คุณสามารถปรับปรุงทุกสิ่งโดยใช้ฟังก์ชั่นวนซ้ำ
for
คุณสามารถวนจาก1
ไปn-1
และนำif
ออกจากร่างกาย ไม่มีจุดตรวจสอบพวกเขาซ้ำ ๆ
คำตอบที่ดีที่สุด:
$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";
}
คำตอบที่มีประสิทธิภาพมากที่สุดจาก @morg ต่างจากforeach
ใช้งานได้กับอาร์เรย์ที่เหมาะสมเท่านั้นไม่ใช้แฮชวัตถุแผนที่ คำตอบนี้หลีกเลี่ยงค่าใช้จ่ายของคำสั่งแบบมีเงื่อนไขสำหรับการวนซ้ำทุกครั้งของลูปในคำตอบส่วนใหญ่ (รวมถึงคำตอบที่ยอมรับ) โดยเฉพาะการจัดการองค์ประกอบแรกและครั้งสุดท้ายและวนลูปกับองค์ประกอบกลาง
array_keys
ฟังก์ชั่นสามารถนำมาใช้เพื่อให้การทำงานมีประสิทธิภาพเช่นคำตอบforeach
:
$keys = array_keys($arr);
$numItems = count($keys);
$i=0;
$firstItem=$arr[$keys[0]];
# Special handling of the first item goes here
$i++;
while($i<$numItems-1){
$item=$arr[$keys[$i]];
# Handling of regular items
$i++;
}
$lastItem=$arr[$keys[$i]];
# Special handling of the last item goes here
$i++;
ฉันยังไม่ได้ทำการเปรียบเทียบในเรื่องนี้ แต่ไม่มีการเพิ่มตรรกะในลูปซึ่งเป็นผลการดำเนินงานที่ยิ่งใหญ่ที่สุดดังนั้นฉันสงสัยว่ามาตรฐานที่ให้มาพร้อมกับคำตอบที่มีประสิทธิภาพนั้นค่อนข้างใกล้เคียง
หากคุณต้องการที่จะfunctionalizeชนิดของสิ่งนี้ผมได้นำการแกว่งที่ดังกล่าวฟังก์ชั่น iterateList ที่นี่ แม้ว่าคุณอาจต้องการเกณฑ์มาตรฐานส่วนสำคัญถ้าคุณกังวลอย่างมากเกี่ยวกับประสิทธิภาพ ฉันไม่แน่ใจว่าค่าใช้จ่ายทั้งหมดที่เรียกใช้ฟังก์ชั่นคือเท่าใด
สำหรับสคริปต์ที่สร้างคิวรี 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: 100,000 รุ่นของ morg
เวลา: 1869.3430423737 มิลลิวินาที
test2: 100,000 รุ่นที่รันล่าสุด
เวลา: 3235.6359958649 มิลลิวินาที
และมันค่อนข้างชัดเจนว่าการตรวจสอบมีค่าใช้จ่ายสูงและแน่นอนว่ายิ่งแย่ลงยิ่งคุณเพิ่มการตรวจสอบตัวแปรมากขึ้น)
$arr = array('one' => "1 1 1", 4 => 'Four', 1 => 'One'); $numItems = count($arr); $i=0; $firstitem=$arr[0]; echo $i . ': ' . $firstitem . ", "; $i++; while($i<$numItems-1){ $some_item=$arr[$i]; echo $i . ': ' . $some_item . ", "; $i++; } $last_item=$arr[$i]; echo $i . ': ' . $last_item . ", "; $i++;
จะส่งออก:0: , 1: One, 2: ,
array()
ทำขึ้น{'one':"1 1 1",0:"",1:"One",2:"",3:"",4:"Four"}
แต่องค์ประกอบที่ว่างเปล่าจะถูกละเว้นด้วยการนับคุณกำลังนับจำนวนสิ่งที่กำหนดไว้ "!! SACRIFICE เข้ามาจำนวนมาก! คำตอบนี้สมควรได้รับความโปรดปราน แต่ถ้า @Morg หายไปมันไร้ประโยชน์ ฉันจะให้รางวัลกับคนที่อาจจะไม่ได้ใช้อีกแล้ว! ถ้าเขากลับมาและปรับปรุงคำตอบของเขาเขาสมควรได้รับรางวัล!
array_keys
ฟังก์ชั่นซึ่งคุณสามารถปฏิบัติได้เหมือนอาเรย์ ดู"ดีขึ้น" ฉันตอบ
$querySet = ""; foreach ($fieldSet as $key=>$value) { $value = $db->dbLink->quote($value); $querySet .= "$key = $value, "; } $querySet = substr_replace($querySet, "", -2); $queryString = "UPDATE users SET $querySet WHERE user_ID = '$user_ID'";
ด้วยคีย์และค่านี้ใช้งานได้เช่นกัน:
foreach ($array as $key => $value) {
if ($value === end($array)) {
echo "LAST ELEMENT!";
}
}
การใช้ตัวแปรบูลีนยังคงเชื่อถือได้มากที่สุดแม้ว่าคุณต้องการตรวจสอบการปรากฏตัวครั้งแรกของ$value
(ฉันพบว่ามันมีประโยชน์มากขึ้นในสถานการณ์ของฉันและในหลาย ๆ สถานการณ์)เช่นนี้:
$is_first = true;
foreach( $array as $value ) {
switch ( $value ) {
case 'match':
echo 'appeared';
if ( $is_first ) {
echo 'first appearance';
$is_first = false;
}
break;
}
}
if( !next( $array ) ) {
echo 'last value';
}
}
จากนั้น!next( $array )
จะหาวิธีสุดท้าย$value
ที่จะกลับมาtrue
หากไม่มีnext()
มูลค่าให้กับสำทับ
และฉันชอบที่จะใช้for
วงวนแทนforeach
ถ้าฉันจะใช้ตัวนับแบบนี้:
$len = count( $array );
for ( $i = 0; $i < $len; $i++ ) {
$value = $array[$i];
if ($i === 0) {
// first
} elseif ( $i === $len - 1 ) {
// last
}
// …
$i++;
}
ฉันเจอกระทู้นี้เมื่อฉันมีปัญหาเดียวกัน ฉันแค่ต้องได้รับองค์ประกอบแรกจากนั้นฉันวิเคราะห์รหัสของฉันอีกครั้งจนกระทั่งสิ่งนี้มาถึงใจของฉัน
$firstElement = true;
foreach ($reportData->result() as $row)
{
if($firstElement) { echo "first element"; $firstElement=false; }
// Other lines of codes here
}
รหัสข้างต้นนั้นยอดเยี่ยมและสมบูรณ์ แต่ถ้าคุณต้องการเพียงแค่องค์ประกอบแรกคุณสามารถลองใช้รหัสนี้ได้
ไม่แน่ใจว่ายังจำเป็นอยู่หรือไม่ แต่การแก้ปัญหาต่อไปนี้ควรทำงานร่วมกับ iterators count
และไม่จำเป็นต้อง
<?php
foreach_first_last(array(), function ($key, $value, $step, $first, $last) {
echo intval($first), ' ', intval($last), ' ', $step, ' ', $value, PHP_EOL;
});
foreach_first_last(array('aa'), function ($key, $value, $step, $first, $last) {
echo intval($first), ' ', intval($last), ' ', $step, ' ', $value, PHP_EOL;
});
echo PHP_EOL;
foreach_first_last(array('aa', 'bb', 'cc'), function ($key, $value, $step, $first, $last) {
echo intval($first), ' ', intval($last), ' ', $step, ' ', $value, PHP_EOL;
});
echo PHP_EOL;
function foreach_first_last($array, $cb)
{
$next = false;
$current = false;
reset($array);
for ($step = 0; true; ++$step) {
$current = $next;
$next = each($array);
$last = ($next === false || $next === null);
if ($step > 0) {
$first = $step == 1;
list ($key, $value) = $current;
if (call_user_func($cb, $key, $value, $step, $first, $last) === false) {
break;
}
}
if ($last) {
break;
}
}
}
คุณสามารถใช้ฟังก์ชันที่ไม่ระบุชื่อเช่นกัน:
$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
ภายในuse
โครงสร้างอีกครั้งโดยอ้างอิงถ้าจำเป็นคุณสามารถใช้ตัวนับและความยาวของอาร์เรย์
$ array = array (1,2,3,4); $ i = 0; $ len = count ($ array); foreach ($ array เป็น $ item) { ถ้า ($ i === 0) { // ก่อน } อื่นถ้า ($ i === $ len - 1) { // ล่าสุด } // … $ i ++; }
foreach ($arquivos as $key => $item) {
reset($arquivos);
// FIRST AHEAD
if ($key === key($arquivos) || $key !== end(array_keys($arquivos)))
$pdf->cat(null, null, $key);
// LAST
if ($key === end(array_keys($arquivos))) {
$pdf->cat(null, null, $key)
->execute();
}
}
การใช้รีเซ็ต ($ array)และสิ้นสุด ($ array)
<?php
$arrays = [1,2,3,4,5];
$first = reset($arrays);
$last = end($arrays);
foreach( $arrays as $array )
{
if ( $first == $array )
{
echo "<li>{$array} first</li>";
}
else if ( $last == $array )
{
echo "<li>{$array} last</li>";
}
else
{
echo "<li>{$array}</li>";
}
}
ลองสิ่งนี้:
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);
array_shift
array_pop
แม้ว่านี่จะเป็นวิธีแก้ปัญหาที่ฉันเกิดขึ้นถ้าฉันต้องทำสิ่งนั้นฉันจะทำตามคำตอบของ Rok Kralj ในตอนนี้