48 votes

Identifier la dernière boucle lors de l'utilisation pour chacun

Je veux faire quelque chose de différent avec la dernière itération de boucle lors de l'exécution de 'foreach' sur un objet. Je suis l'aide de Ruby, mais il en va de même pour C#, Java, etc.

  list = ['A','B','C']
  list.each{|i|
    puts "Looping: "+i # if not last loop iteration
    puts "Last one: "+i # if last loop iteration
  }

La sortie désirée est équivalent à:

  Looping: 'A'
  Looping: 'B'
  Last one: 'C'

La solution évidente est de migrer le code d'une boucle à l'aide de 'for i in 1..list.length', mais la solution se sent plus gracieux. Quelle est la façon la plus discrète pour code un cas particulier au cours d'une boucle? Peut-il être fait avec foreach?

38voto

Bigjim Points 406

Je vois beaucoup de code complexe, à peine lisible ici ... pourquoi ne pas le garder simple:

 var count = list.Length;

foreach(var item in list)
    if (--count > 0)
        Console.WriteLine("Looping: " + item);
    else
        Console.Writeline("Lastone: " + item);
 

Ce n'est qu'une déclaration supplémentaire!

Une autre situation courante est que vous voulez faire quelque chose de plus ou de moins avec le dernier élément, comme mettre un séparateur entre les éléments:

 var count = list.Length;

foreach(var item in list)
{
    Console.Write(item);
    if (--count > 0)
        Console.Write(",");
}
 

37voto

Michael Borgwardt Points 181658

La construction foreach (en Java certainement, probablement aussi dans d’autres langages) est censée représenter le type le plus général si l’itération, qui inclut l’itération sur des collections qui n’ont pas d’ordre d’itération significatif. Par exemple, un ensemble basé sur un hachage n'a pas d'ordre, et par conséquent, il n'y a pas de "dernier élément". La dernière itération peut générer un élément différent à chaque itération.

Fondamentalement: non, la construction foreach n'est pas conçue pour être utilisée de cette façon.

23voto

anonymous Points 417

Comment obtenir une référence vers le dernier élément de la première et de l'utiliser ensuite à des fins de comparaison à l'intérieur de la boucle foreach? Je ne suis pas dire que vous devriez le faire que je me serait d'utiliser l'indice de boucle, comme mentionné par KlauseMeier. Et désolé, je ne connais pas Ruby donc l'exemple suivant est en C#! L'espérance de u dont l'esprit :-)

string lastItem = list[list.Count - 1];
foreach (string item in list) {
    if (item != lastItem)
    	Console.WriteLine("Looping: " + item);
    else	Console.Writeline("Lastone: " + item);
}

J'ai revu le code suivant pour comparer par référence non valeur (utiliser uniquement les types de référence pas de types de valeur). le code suivant devrait soutenir plusieurs objets contenant de la même chaîne (mais pas le même objet de type string) depuis MattChurcy l'exemple ne précise pas que les cordes doivent être distinctes et j'ai utilisé LINQ Dernière méthode de calcul de l'indice.

string lastItem = list.Last();
foreach (string item in list) {
    if (!object.ReferenceEquals(item, lastItem))
        Console.WriteLine("Looping: " + item);
    else        Console.WriteLine("Lastone: " + item);
}

Les Limitations du code ci-dessus. (1) Il ne peut fonctionner que pour des chaînes ou des types de référence pas de types de valeur. (2) Même objet ne peut apparaître qu'une fois dans la liste. Vous pouvez avoir différents objets contenant le même contenu. Les chaînes littérales ne peut pas être utilisé à plusieurs reprises depuis C# ne pas créer un objet unique pour les chaînes qui ont le même contenu.

Et j'ai pas stupide. Je connais un indice de boucle est celle à utiliser. Je l'ai déjà dit quand j'ai posté la réponse initiale. J'ai apporté la meilleure réponse que je peux dans le contexte de la question. Je suis trop fatigué pour garder expliquant ce donc, pouvez-vous tout simplement voter pour supprimer ma réponse. Je serai donc heureux si celui-ci s'en va. merci

22voto

kgiannakakis Points 62727

Est-ce assez élégant? Cela suppose une liste non vide.

   list[0,list.length-1].each{|i|
    puts "Looping:"+i # if not last loop iteration
  }
  puts "Last one:" + list[list.length-1]
 

13voto

David Burrows Points 3023

En Ruby, j'utiliserais each_with_index dans cette situation

 list = ['A','B','C']
last = list.length-1
list.each_with_index{|i,index|
  if index == last 
    puts "Last one: "+i 
  else 
    puts "Looping: "+i # if not last loop iteration
  end
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X