A questão é simples. Eu tenho um foreach
loop no meu código:
foreach($array as $element) {
//code
}
Nesse loop, quero reagir de maneira diferente quando estivermos na primeira ou na última iteração.
Como fazer isso?
Você pode usar um contador:
$i = 0;
$len = count($array);
foreach ($array as $item) {
if ($i == 0) {
// first
} else if ($i == $len - 1) {
// last
}
// …
$i++;
}
array_shift
earray_pop
. Embora essa seja a solução que eu surgisse se tivesse que implementar uma coisa dessas, continuaria com a resposta do Rok Kralj .$i = 1
, não precisa se preocupar$len - 1
, basta usar$len
.Se você preferir uma solução que não exija a inicialização do contador fora do loop, proponho comparar a chave de iteração atual com a função que indica a última / primeira chave da matriz.
Isso se torna um pouco mais eficiente (e mais legível) com o próximo PHP 7.3.
Solução para PHP 7.3 e superior:
Solução para todas as versões do PHP:
fonte
end()
+key()
em todas as iterações do loop - se são os dois, são 4 métodos sendo chamados sempre. É verdade que essas operações seriam muito leves e provavelmente são apenas pesquisas de ponteiro, mas os documentos continuam especificando issoreset()
eend()
modificando o ponteiro interno da matriz - então é mais rápido que um contador? possivelmente não.reset()
chamada antes do foreach e armazenar em cache o resultado$first
.Para encontrar o último item, acho que esse código funciona sempre:
fonte
next
: Aviso Essa função pode retornar booleanoFALSE
, mas também pode retornar um valor não booleano que é avaliado comoFALSE
. Por favor, leia a seção Booleans para mais informações. Use o===
operador para testar o valor de retorno desta função.[true,true,false,true]
. Mas, pessoalmente, usarei isso sempre que estiver lidando com uma matriz que não contém booleanofalse
.next()
NUNCA deve ser usado dentro de um loop foreach. Ele atrapalha o ponteiro interno da matriz. Confira a documentação para mais informações.Uma versão mais simplificada das opções acima e presumindo que você não esteja usando índices personalizados ...
Versão 2 - Porque vim detestar o uso do else a menos que seja necessário.
fonte
if ($index == count($array) - 1)
. Veja aqui .Você pode remover o primeiro e o último elementos da matriz e processá-los separadamente.
Como isso:
A remoção de toda a formatação para CSS em vez de tags embutidas melhoraria seu código e aceleraria o tempo de carregamento.
Você também pode evitar misturar HTML com lógica php sempre que possível.
Sua página pode ficar muito mais legível e mantida separando coisas como esta:
fonte
Uma tentativa de encontrar o primeiro seria:
fonte
Simplesmente isso funciona!
Obrigado @billynoah por resolver a questão final .
fonte
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()
está recebendo um número inteiro, nãoend()
.end()
" retorna o valor do último elemento " ekey()
espera uma matriz como entrada.1: Por que não usar uma
for
declaração simples ? Supondo que você esteja usando uma matriz real e não uma,Iterator
você pode facilmente verificar se a variável do contador é 0 ou menos que o número inteiro de elementos. Na minha opinião, esta é a solução mais limpa e compreensível ...2: você deve considerar o uso de conjuntos aninhados para armazenar sua estrutura em árvore. Além disso, você pode melhorar tudo usando funções recursivas.
fonte
for
que você pode fazer um loop a partir1
den-1
e tomar oif
é fora do corpo. Não faz sentido checá-los repetidamente.Melhor resposta:
fonte
A resposta mais eficiente do @morg, ao contrário
foreach
, funciona apenas para matrizes apropriadas, não para objetos de mapa de hash. Essa resposta evita a sobrecarga de uma declaração condicional para cada iteração do loop, como na maioria dessas respostas (incluindo a resposta aceita), manipulando especificamente o primeiro e o último elemento e repetindo os elementos do meio.A
array_keys
função pode ser usada para fazer a resposta eficiente funcionar comoforeach
:Eu não fiz benchmarking sobre isso, mas nenhuma lógica foi adicionada ao loop, que foi o maior impacto no desempenho, então eu suspeitaria que os benchmarks fornecidos com a resposta eficiente estão bem próximos.
Se você quisesse funcionalizar esse tipo de coisa, aceitei uma função iterateList aqui . No entanto, convém comparar o código de essência se você estiver super preocupado com a eficiência. Não tenho certeza de quanto sobrecarga toda a chamada de função introduz.
fonte
Para scripts geradores de consultas SQL, ou qualquer coisa que execute uma ação diferente para o primeiro ou o último elemento, é muito mais rápido (quase o dobro da velocidade) evitar o uso de verificações desnecessárias de variáveis.
A solução atual aceita usa um loop e uma verificação dentro do loop que será feita a cada_a única_iteração, a maneira correta (rápida) de fazer isso é a seguinte:
Um pequeno benchmark caseiro mostrou o seguinte:
test1: 100000 execuções do modelo morg
tempo: 1869.3430423737 milissegundos
test2: 100000 execuções do modelo, se houver
tempo: 3235.6359958649 milissegundos
E, portanto, fica bem claro que a verificação custa muito e, é claro, fica ainda pior quanto mais verificações variáveis você adicionar;)
fonte
$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++;
irá produzir:0: , 1: One, 2: ,
array()
criado é{'one':"1 1 1",0:"",1:"One",2:"",3:"",4:"Four"}
mas os elementos vazios são ignorados com count, você está contando o número de "coisas" definidas !! SACRIFÍCIO RECONHECIDO! Esta resposta merece recompensa, mas se @Morg. se foi, é inútil. Eu daria recompensa a uma pessoa que provavelmente não usaria o SO novamente! Se ele voltar e melhorar sua resposta, ele merece a recompensa!array_keys
função, que pode ser tratada como uma matriz. Veja minha resposta "aprimorada" .$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'";
Com Chaves e Valores, isso também funciona:
fonte
O uso de uma variável booleana ainda é a mais confiável, mesmo se você quiser verificar a primeira aparência de a
$value
(achei mais útil na minha situação e em muitas situações) , como esta:Então, que tal
!next( $array )
encontrar o último$value
que retornarátrue
se não houvernext()
valor para iterar.E eu prefiro usar um
for
loop em vez deforeach
usar um contador, como este:fonte
Me deparei com esta discussão quando tenho o mesmo problema. Eu só preciso obter o primeiro elemento e depois re-analisar meu código até que isso me ocorreu.
Os códigos acima são ótimos e completos, mas se você precisar apenas do primeiro elemento, poderá tentar esse código.
fonte
Não tenho certeza se ainda é necessário. Mas a solução a seguir deve funcionar com iteradores e não requer
count
.fonte
Você também pode usar uma função anônima:
Mais três coisas devem ser mencionadas:
array_values
primeiro.$element
precisará passar por referência (&$element
).$indexOfLastElement
dentro dause
construção, novamente por referência, se necessário.fonte
Você pode usar o contador e o comprimento da matriz.
fonte
fonte
Usando reset ($ array) e end ($ array)
Demo repl.it
fonte
Tente o seguinte:
fonte