Odpowiedzi:
Możesz użyć licznika:
$i = 0;
$len = count($array);
foreach ($array as $item) {
if ($i == 0) {
// first
} else if ($i == $len - 1) {
// last
}
// …
$i++;
}
$i = 1
, nie musisz się martwić $len - 1
, po prostu użyj $len
.
Jeśli wolisz rozwiązanie, które nie wymaga inicjalizacji licznika poza pętlą, proponuję porównanie bieżącego klucza iteracji z funkcją, która mówi ci ostatni / pierwszy klucz tablicy.
Staje się to nieco bardziej wydajne (i bardziej czytelne) w nadchodzącym 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()
na każdej iteracji pętli - jeśli to obie, to za każdym razem wywoływane są 4 metody. To prawda, że byłyby to bardzo lekkie operacje i prawdopodobnie są to po prostu wyszukiwanie wskaźników, ale potem dokumenty określają to reset()
i end()
modyfikują wewnętrzny wskaźnik tablicy - więc czy jest szybszy niż licznik? być może nie.
reset()
rozmowę przed foreach i zapisać wynik w pamięci podręcznej $first
.
Aby znaleźć ostatni element, uważam, że ten fragment kodu działa za każdym razem:
foreach( $items as $item ) {
if( !next( $items ) ) {
echo 'Last Item';
}
}
[true,true,false,true]
. Ale osobiście będę tego używał za każdym razem, gdy mam do czynienia z tablicą, która nie zawiera wartości logicznej false
.
next()
NIGDY nie powinien być używany wewnątrz pętli foreach. Zmiesza wskaźnik wewnętrzny tablicy. Sprawdź dokumentację, aby uzyskać więcej informacji.
Bardziej uproszczona wersja powyższego i zakładając, że nie używasz niestandardowych indeksów ...
$len = count($array);
foreach ($array as $index => $item) {
if ($index == 0) {
// first
} else if ($index == $len - 1) {
// last
}
}
Wersja 2 - Ponieważ nienawidzę używać innych, chyba że jest to konieczne.
$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)
. Zobacz tutaj .
Możesz usunąć pierwszy i ostatni element z tablicy i przetwarzać je osobno.
Lubię to:
<?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
?>
Usunięcie całego formatowania do CSS zamiast tagów wbudowanych poprawiłoby kod i przyspieszyło ładowanie.
W miarę możliwości można także unikać mieszania HTML z logiką php.
Twoja strona może stać się o wiele bardziej czytelna i łatwa w utrzymaniu, dzieląc takie rzeczy:
<?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
}
?>
Próbą znalezienia pierwszego byłoby:
$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
}
}
Po prostu to działa!
// 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];
}
Dziękuję @billynoah za rozwiązanie problemu końcowego .
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()
otrzymuje liczbę całkowitą, nie end()
. end()
„ zwraca wartość ostatniego elementu ” i key()
oczekuje tablicy jako danych wejściowych.
1: Dlaczego nie użyć prostego for
stwierdzenia? Zakładając, że używasz prawdziwej tablicy, a nie an, Iterator
możesz łatwo sprawdzić, czy zmienna licznika jest równa 0, czy jeden mniejsza niż cała liczba elementów. Moim zdaniem jest to najbardziej czyste i zrozumiałe rozwiązanie ...
$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: Należy rozważyć użycie zestawów zagnieżdżonych do przechowywania struktury drzewa. Dodatkowo możesz ulepszyć całość, korzystając z funkcji rekurencyjnych.
for
można od pętli 1
do n-1
i wziąć if
s poza ciałem. Nie ma sensu sprawdzać ich wielokrotnie.
Najlepsza odpowiedź:
$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";
}
Najbardziej wydajna odpowiedź z @morg, w przeciwieństwie do foreach
, działa tylko dla odpowiednich tablic, a nie dla obiektów mapy mieszania. Ta odpowiedź pozwala uniknąć narzutu instrukcji warunkowej dla każdej iteracji pętli, tak jak w większości tych odpowiedzi (w tym odpowiedzi zaakceptowanej) poprzez specyficzną obsługę pierwszego i ostatniego elementu oraz zapętlanie elementów środkowych.
array_keys
Funkcja może być użyta do dokonania efektywnej pracy odpowiedzi jak 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++;
Nie przeprowadziłem testów porównawczych w tym zakresie, ale do pętli nie dodano żadnej logiki, która jest największym hitem wydajności, więc podejrzewam, że testy porównawcze z wydajną odpowiedzią są dość zbliżone.
Jeśli chcesz funkcjonalizować tego rodzaju rzeczy, podważyłem tutaj funkcję iterateList . Możesz jednak chcieć przetestować kod GIST, jeśli bardzo martwisz się wydajnością. Nie jestem pewien, ile narzucają wszystkie wywołania funkcji.
W przypadku skryptów generujących zapytania SQL lub czegokolwiek, co wykonuje inną akcję dla pierwszego lub ostatniego elementu, jest to znacznie szybsze (prawie dwa razy szybsze), aby uniknąć niepotrzebnego sprawdzania zmiennych.
Obecnie akceptowane rozwiązanie wykorzystuje pętlę i sprawdzanie w pętli, które będzie wykonywane co każde pojedyncze sformułowanie, poprawny (szybki) sposób to zrobić:
$numItems = count($arr);
$i=0;
$firstitem=$arr[0];
$i++;
while($i<$numItems-1){
$some_item=$arr[$i];
$i++;
}
$last_item=$arr[$i];
$i++;
Mały domowy test porównawczy pokazał, co następuje:
test1: 100000 serii modelu Morg
czas: 1869.3430423737 milisekund
test2: 100000 serii modelu, jeśli ostatnia
czas: 3235.6359958649 milisekund
I dlatego jest całkiem jasne, że czek kosztuje dużo i oczywiście staje się jeszcze gorzej, gdy dodajesz więcej zmiennych czeków;)
$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++;
wyświetli:0: , 1: One, 2: ,
array()
jest, {'one':"1 1 1",0:"",1:"One",2:"",3:"",4:"Four"}
ale puste elementy są ignorowane przy pomocy count, liczy się liczba zdefiniowanych „rzeczy” !! BOUNTY OFIARY POCHODZĄCE! Ta odpowiedź zasługuje na nagrodę, ale jeśli @Morg. odszedł, to nie ma sensu. Dałbym nagrodę osobie, która prawdopodobnie nie użyje SO ponownie! Jeśli wróci i poprawi odpowiedź, zasługuje na nagrodę!
array_keys
funkcji, którą można traktować jak tablicę. Zobacz moją „ulepszoną” odpowiedź .
$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'";
W przypadku kluczy i wartości działa to również:
foreach ($array as $key => $value) {
if ($value === end($array)) {
echo "LAST ELEMENT!";
}
}
Korzystanie ze zmiennej boolowskiej jest nadal najbardziej niezawodne, nawet jeśli chcesz sprawdzić pierwsze pojawienie się zmiennej $value
(uznałem ją za bardziej przydatną w mojej sytuacji i w wielu sytuacjach) , na przykład:
$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';
}
}
Więc jak !next( $array )
znaleźć ostatni, $value
który zwróci, true
jeśli nie ma next()
wartości do iteracji.
I wolę użyć for
pętli, niż foreach
gdybym miał użyć licznika, takiego jak to:
$len = count( $array );
for ( $i = 0; $i < $len; $i++ ) {
$value = $array[$i];
if ($i === 0) {
// first
} elseif ( $i === $len - 1 ) {
// last
}
// …
$i++;
}
Natknąłem się na ten wątek, gdy mam ten sam problem. Muszę tylko zdobyć pierwszy element, a następnie ponownie przeanalizować kod, dopóki nie przyszło mi to do głowy.
$firstElement = true;
foreach ($reportData->result() as $row)
{
if($firstElement) { echo "first element"; $firstElement=false; }
// Other lines of codes here
}
Powyższe kody są świetne i kompletne, ale jeśli potrzebujesz tylko pierwszego elementu, możesz wypróbować ten kod.
Nie jestem pewien, czy nadal jest to konieczne. Ale poniższe rozwiązanie powinno współpracować z iteratorami i nie wymaga 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;
}
}
}
Możesz także użyć funkcji anonimowej:
$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
}
});
Należy wymienić jeszcze trzy rzeczy:
array_values
.$element
, musisz przekazać go przez referencję ( &$element
).$indexOfLastElement
wewnątrz use
konstrukcji, przez odniesienie ponownie w razie potrzeby.Możesz użyć licznika i długości tablicy.
$ tablica = tablica (1,2,3,4); $ i = 0; $ len = liczba ($ tablica); foreach ($ tablica jako $ element) { jeśli ($ i === 0) { // pierwszy } else if ($ i === $ len - 1) { // ostatni, ubiegły, zeszły } //… $ 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();
}
}
Korzystanie z resetowania ($ array) i end ($ 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>";
}
}
Spróbuj tego:
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
iarray_pop
. Chociaż to jest rozwiązanie, które wymyśliłem, gdybym musiał wdrożyć coś takiego, trzymałbym się teraz odpowiedzi Rok Kralja .