Trouver le dernier élément d'un tableau en utilisant une boucle foreach en PHP
J'écris un créateur de requête SQL en utilisant certains paramètres. En Java, il est très facile de détecter le dernier élément d'un tableau à l'intérieur de la boucle for en vérifiant simplement la position actuelle du tableau avec la longueur du tableau.
for(int i=0; i< arr.length;i++){
boolean isLastElem = i== (arr.length -1) ? true : false;
}
En PHP, ils ont des index non entiers pour accéder aux tableaux. Vous devez donc itérer sur un tableau en utilisant une boucle foreach. Cela devient problématique lorsque vous devez prendre une décision (dans mon cas pour ajouter ou/et paramètre lors de la construction de la requête).
Je suis sûr il doit y avoir une manière standard de le faire.
Comment résolvez - vous cela en PHP?
29 réponses
On dirait que vous voulez quelque chose comme ceci:
$numItems = count($arr);
$i = 0;
foreach($arr as $key=>$value) {
if(++$i === $numItems) {
echo "last index!";
}
}
Cela étant dit, vous n'avez pas à itérer sur un "tableau" en utilisant foreach
en php.
Vous pouvez obtenir la valeur de la dernière clé du tableau en utilisant end(array_keys($array))
et la comparer à la clé actuelle:
$last_key = end(array_keys($array));
foreach ($array as $key => $value) {
if ($key == $last_key) {
// last element
} else {
// not last element
}
}
Pourquoi si compliqué?
foreach($input as $key => $value) {
$ret .= "$value";
if (next($input)==true) $ret .= ",";
}
Cela ajoutera un, derrière chaque valeur sauf la dernière!
Quand toEnd atteint 0, cela signifie qu'il est à la dernière itération de la boucle.
$toEnd = count($arr);
foreach($arr as $key=>$value) {
if (0 === --$toEnd) {
echo "last index! $value";
}
}
, La dernière valeur est toujours disponible après la boucle, donc si vous voulez l'utiliser pour des choses plus après la boucle, c'est mieux:
foreach($arr as $key=>$value) {
//something
}
echo "last index! $key => $value";
Si vous ne voulez pas traiter la dernière valeur comme des boucles intérieures spéciales. Cela devrait être plus rapide si vous avez de grands tableaux. (Si vous réutilisez le tableau après la boucle dans la même portée, vous devez d'abord "copier" le tableau).
//If you use this in a large global code without namespaces or functions then you can copy the array like this:
//$array = $originalArrayName; //uncomment to copy an array you may use after this loop
//end($array); $lastKey = key($array); //uncomment if you use the keys
$lastValue = array_pop($array);
//do something special with the last value here before you process all the others?
echo "Last is $lastValue", "\n";
foreach ($array as $key => $value) {
//do something with all values before the last value
echo "All except last value: $value", "\n";
}
//do something special with the last value here after you process all the others?
echo "Last is $lastValue", "\n";
Et de répondre à votre question originale "dans mon cas pour ajouter ou/et paramètre lors de la construction de la requête"; cela va faire une boucle sur toutes les valeurs, puis les joindre à une chaîne avec " et " entre eux mais pas avant la première valeur ou après la dernière valeur:
$params = [];
foreach ($array as $value) {
$params[] = doSomething($value);
}
$parameters = implode(" and ", $params);
Il y a déjà beaucoup de réponses, mais il vaut la peine de regarder dans les itérateurs, d'autant plus qu'il a été demandé de manière standard:
$arr = range(1, 3);
$it = new CachingIterator(new ArrayIterator($arr));
foreach($it as $key => $value)
{
if (!$it->hasNext()) echo 'Last:';
echo $value, "\n";
}
Vous pourriez trouver quelque chose qui fonctionne plus flexible pour d'autres cas, aussi.
Donc, si votre tableau a des valeurs de tableau uniques, la détermination de la dernière itération est triviale:
foreach($array as $element) {
if ($element === end($array))
echo 'LAST ELEMENT!';
}
Comme vous le voyez, cela fonctionne si le dernier élément n'apparaît qu'une seule fois dans le tableau, sinon vous obtenez une fausse alerte. Dans ce n'est pas, vous devez comparer les clés (qui sont uniques à coup sûr).
foreach($array as $key => $element) {
end($array);
if ($key === key($array))
echo 'LAST ELEMENT!';
}
Notez également l'opérateur de coparision strict, ce qui est très important dans ce cas.
En Supposant que vous avez le tableau stocké dans une variable...
foreach($array as $key=>$value)
{
echo $value;
if($key != count($array)-1) { echo ", "; }
}
Une façon peut être de détecter si l'itérateur a next
. S'il n'y a pas de next attaché à l'itérateur, cela signifie que vous êtes dans la dernière boucle.
foreach ($some_array as $element) {
if(!next($some_array)) {
// This is the last $element
}
}
Si vous devez faire quelque chose pour chaque élément sauf le premier ou le dernier et seulement s'il y a plus d'un élément dans le tableau, je préfère la solution suivante.
Je sais qu'il y a beaucoup de solutions ci-dessus et affichées des mois/un an avant la mienne, mais c'est quelque chose que je pense être assez élégant en soi. La vérification de chaque boucle est également une vérification booléenne par opposition à une vérification numérique "i=(count-1)", ce qui peut permettre moins de surcharge.
La structure de la boucle peut sentez-vous maladroit, mais vous pouvez le comparer à l'ordre de thead (début), tfoot (fin), tbody (courant) dans les balises de table HTML.
$first = true;
foreach($array as $key => $value) {
if ($first) {
$first = false;
// Do what you want to do before the first element
echo "List of key, value pairs:\n";
} else {
// Do what you want to do at the end of every element
// except the last, assuming the list has more than one element
echo "\n";
}
// Do what you want to do for the current element
echo $key . ' => ' . $value;
}
Par exemple, en termes de développement web, si vous voulez ajouter un border-bottom à chaque élément sauf le dernier dans une liste non ordonnée (ul), vous pouvez plutôt Ajouter un border-top à chaque élément sauf le premier (le CSS: first-child, supporté par IE7+ et Firefox / Webkit supporte cette logique, alors que: last-child IE7).
Vous pouvez également réutiliser la variable $first pour chaque boucle imbriquée et les choses fonctionneront très bien puisque chaque boucle fait $first false pendant le premier processus de la première itération (donc les pauses / exceptions ne causeront pas de problèmes).
$first = true;
foreach($array as $key => $subArray) {
if ($first) {
$string = "List of key => value array pairs:\n";
$first = false;
} else {
echo "\n";
}
$string .= $key . '=>(';
$first = true;
foreach($subArray as $key => $value) {
if ($first) {
$first = false;
} else {
$string .= ', ';
}
$string .= $key . '=>' . $value;
}
$string .= ')';
}
echo $string;
Exemple de sortie:
List of key => value array pairs:
key1=>(v1_key1=>v1_val1, v1_key2=>v1_val2)
key2=>(v2_key1=>v2_val1, v2_key2=>v2_val2, v2_key3=>v2_val3)
key3=>(v3_key1=>v3_val1)
Vous pouvez toujours utiliser cette méthode avec des tableaux associatifs:
$keys = array_keys($array);
for ($i = 0, $l = count($array); $i < $l; ++$i) {
$key = $array[$i];
$value = $array[$key];
$isLastItem = ($i == ($l - 1));
// do stuff
}
// or this way...
$i = 0;
$l = count($array);
foreach ($array as $key => $value) {
$isLastItem = ($i == ($l - 1));
// do stuff
++$i;
}
J'ai un fort sentiment qu'à la racine de ce "problème XY" L'OP voulait juste la fonction implode()
.
Comme votre intention de trouver le tableau EOF est juste pour la colle. Présentez-vous à la tactique ci-dessous. Vous n'avez pas besoin de l'EOF:
$given_array = array('column1'=>'value1',
'column2'=>'value2',
'column3'=>'value3');
$glue = '';
foreach($given_array as $column_name=>$value){
$where .= " $glue $column_name = $value"; //appending the glue
$glue = 'AND';
}
echo $where;
O / p:
column1 = value1 AND column2 = value2 AND column3 = value3
Il semble que vous voulez quelque chose comme ceci:
$array = array(
'First',
'Second',
'Third',
'Last'
);
foreach($array as $key => $value)
{
if(end($array) === $value)
{
echo "last index!" . $value;
}
}
, Vous pouvez faire un count().
for ($i=0;$i<count(arr);$i++){
$i == count(arr)-1 ? true : false;
}
Ou si vous ne cherchez que le dernier élément, vous pouvez utiliser end ().
end(arr);
Renvoie uniquement le dernier élément.
Et, comme il s'avère, vous pouvez indexer les tableaux php par des entiers. Il est parfaitement heureux avec
arr[1];
Que diriez-vous d'utiliser "end"? http://php.net/manual/en/function.end.php
Vous pouvez aussi faire quelque chose comme ceci:
end( $elements );
$endKey = key($elements);
foreach ($elements as $key => $value)
{
if ($key == $endKey) // -- this is the last item
{
// do something
}
// more code
}
J'aime un peu ce qui suit car je pense que c'est assez soigné. Supposons que nous créons une chaîne avec des séparateurs entre tous les éléments: par exemple a,b, c
$first = true;
foreach ( $items as $item ) {
$str = ($first)?$first=false:", ".$item;
}
Voici une autre façon de le faire:
$arr = range(1, 10);
$end = end($arr);
reset($arr);
while( list($k, $v) = each($arr) )
{
if( $n == $end )
{
echo 'last!';
}
else
{
echo sprintf('%s ', $v);
}
}
Si je vous comprends, alors tout ce dont vous avez besoin est d'inverser le tableau et d'obtenir le dernier élément par une commande pop:
$rev_array = array_reverse($array);
echo array_pop($rev_array);
Vous pouvez également essayer ceci pour faire votre requête... montré ici avec INSERT
<?php
$week=array('one'=>'monday','two'=>'tuesday','three'=>'wednesday','four'=>'thursday','five'=>'friday','six'=>'saturday','seven'=>'sunday');
$keys = array_keys($week);
$string = "INSERT INTO my_table ('";
$string .= implode("','", $keys);
$string .= "') VALUES ('";
$string .= implode("','", $week);
$string .= "');";
echo $string;
?>
Pour les scripts de génération de requêtes SQL, ou tout ce qui fait une action différente pour le premier ou le dernier élément, il est beaucoup plus rapide (presque deux fois plus rapide) d'éviter d'utiliser des vérifications de variables inutiles.
La solution acceptée actuelle utilise une boucle et une vérification dans la boucle qui sera faite every_single_iteration, la manière correcte (rapide) de le faire est la suivante:
$numItems = count($arr);
$i=0;
$firstitem=$arr[0];
$i++;
while($i<$numItems-1){
$some_item=$arr[$i];
$i++;
}
$last_item=$arr[$i];
$i++;
Un petit benchmark fait maison a montré ce qui suit:
Test1: 100000 courses de modèle morg
Temps: 1869.3430423737 millisecondes
Test2: 100000 essais du modèle si dernier
Temps: 3235.6359958649 millisecondes
Une autre façon de procéder est de se souvenir du résultat du cycle de boucle précédent et de l'utiliser comme résultat final:
$result = $where = "";
foreach ($conditions as $col => $val) {
$result = $where .= $this->getAdapter()->quoteInto($col.' = ?', $val);
$where .= " AND ";
}
return $this->delete($result);
Personnellement, j'utilise ce type de construction qui permet une utilisation facile avec les éléments html et : il suffit de changer l'égalité pour une autre propriété...
Le tableau ne peut pas contenir de faux éléments mais tous les autres éléments qui sont convertis dans le faux booléen.
$table = array( 'a' , 'b', 'c');
$it = reset($table);
while( $it !== false ) {
echo 'all loops';echo $it;
$nextIt = next($table);
if ($nextIt === false || $nextIt === $it) {
echo 'last loop or two identical items';
}
$it = $nextIt;
}
Vous pouvez directement obtenir le dernier index par:
$numItems = count($arr);
echo $arr[$numItems-1];
<?php foreach($have_comments as $key => $page_comment): ?>
<?php echo $page_comment;?>
<?php if($key+1<count($have_comments)): ?>
<?php echo ', '; ?>
<?php endif;?>
<?php endforeach;?>
Voici ma solution: Obtenez simplement le nombre de votre tableau, moins 1 (puisqu'ils commencent en 0).
$lastkey = count($array) - 1;
foreach($array as $k=>$a){
if($k==$lastkey){
/*do something*/
}
}
foreach ($array as $key => $value) {
$class = ( $key !== count( $array ) -1 ) ? " class='not-last'" : " class='last'";
echo "<div{$class}>";
echo "$value['the_title']";
echo "</div>";
}
J'ai une solution généralisée que j'utilise, dans le but commun de compiler une chaîne à partir d'un tableau de valeurs de chaîne. Tout ce que je fais est d'ajouter une chaîne inhabituelle à la fin, puis de la remplacer.
Fonction Pour renvoyer une chaîne d'un tableau, séparée, sans séparateur de fin:
function returnArraySeparated($aArr, $sSep, $sAdd = "@X@") {
$strReturn = (string) "";
# Compile the set:
foreach ($aArr as $sItem) {
$strReturn .= $sItem . $sSep;
}
# Easy strip the end:
$strReturn = str_replace($sSep . $sAdd, "", $strReturn . $sAdd);
return $strReturn;
}
Rien de spécial, mais ça marche:)