L'identification de la dernière boucle lors de l'utilisation de chaque
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'
L'évidente solution de contournement 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?
- Merci à tous pour les grands et les diverses réponses. Je vois ce que les gens disent à propos de collections n'ayant pas toujours un ordre. Mais, à certains moments, les collections ont un ordre et je ne vois pas pourquoi pour chaque boucle ne doit pas toujours s'appliquer.
- Désolé que je ne pouvez sélectionner qu'une seule réponse, je fais comme la plupart d'entre eux.
- dommage que vous n'avez pas sélectionné l'un des meilleurs.
Vous devez vous connecter pour publier un commentaire.
Comment sur l'obtention d'un référence à la dernier élément d'abord et ensuite l'utiliser pour la 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 🙂
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.
Limites 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 la 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. grâce
foreach
boucle à unfor
boucle quand ce que vous avez réellement besoin est unefor
boucle. Et vous avez besoin d'unfor
boucle parce que vous avez besoin de l'index en cours afin de déterminer si vous êtes actuellement sur le dernier indice.La construction foreach (en Java certainement, probablement aussi dans d'autres langues) est destiné à représenter le plus grand type si itération, qui comprend une itération sur les collections qui n'ont pas véritablement itération de l'ordre. Par exemple, une base de hachage qui n'en possède pas un ordre, et, par conséquent, il n'y est pas "dernier élément". La dernière itération peut donner un aspect différent à chaque itération.
En gros: non, la structure foreach n'est pas destiné à être utilisé de cette façon.
Je vois beaucoup de complexe, difficilement lisible le code ici... pourquoi ne pas faire simple:
C'est seulement une déclaration de!
Une autre commune de la situation, c'est que vous voulez faire quelque chose de plus ou moins avec le dernier élément, comme mettre un séparateur entre les éléments:
Est cet élégant assez? Il suppose une non-vide de la liste.
En Ruby, j'utiliserais
each_with_index
dans cette situationVous pouvez définir un
eachwithlast
méthode dans votre classe pour faire la même chose queeach
sur tous les éléments, mais le dernier, mais quelque chose d'autre pour le dernier:Ensuite, vous pouvez l'appeler comme cela (
foo
étant une instance deMyColl
ou une sous-classe de celle-ci):Edit: Suivantes molf suggestion:
C# 3.0 ou plus récent
Tout d'abord, je voudrais écrire une méthode d'extension:
Puis à l'aide de la nouvelle
foreach
est très simple:Iterable
s qui ne sont pasList
s. +1.Vous devez utiliser foreach seulement si vous manipulez des chaque même. L'utilisation de l'indice de base interaction à la place. D'autre, vous devez ajouter une autre structure autour des éléments, que vous pouvez utiliser pour différencier la normale à partir de la dernière dans le foreach appel (regardez dans les bons Papiers sur la carte réduite de google pour le fond: http://labs.google.com/papers/mapreduce.html, la carte == foreach, réduit == par exemple, la somme ou le filtre).
Carte n'a pas de connaissances sur la structure (de l'esp. la position d'un élément), il transforme un élément par élément (pas de connaissances à partir d'un élément peut être utilisé pour transformer un d'autres!), mais réduire peut utiliser une mémoire, par exemple, à compter de la position de la poignée et le dernier élément.
Un truc commun est de renverser la liste et faire face à la première (qui est maintenant connu index = 0), et par la suite, demander inverse à nouveau. (Qui est élégant mais pas rapide 😉 )
Foreach est à la fois élégante qu'il n'a aucun souci pour le nombre d'éléments dans une liste et traite chaque élément également, je pense que votre seule solution sera à l'aide d'une boucle qui s'arrête à itemcount-1 et ensuite vous présenter votre dernier point à l'extérieur de la boucle conditionnelle à l'intérieur de la boucle qui gère cet état spécifique, c'est à dire si (i==itemcount) { ... } else { ... }
Vous pourriez faire quelque chose comme ça (en C#) :
Ruby a également each_index méthode:
EDIT:
Ou de l'utilisation de chacun (corrigé TomatoGG et Kirschstein solution):
Ou
Ce que vous essayez de faire de semble juste un peu trop avancé pour le foreach de la boucle. Toutefois, vous pouvez utiliser
Iterator
s explicitement. Par exemple, en Java, je voudrais écrire ceci:Si vous utilisez une collection qui expose une
Count
bien - une hypothèse faite par de nombreux autres réponses, je vais donc en faire trop - ensuite, vous pouvez faire quelque chose comme ceci à l'aide de C# et de LINQ:En outre, si nous supposons que les éléments de la collection peut être consulté directement par index - actuellement accepté de répondre à assume cette - puis une plaine
for
boucle sera plus élégant/lisible qu'unforeach
:Si la collection n'expose pas de
Count
de propriété et ne peut être accédé par l'indice, il n'y a pas vraiment de moyen élégant pour ce faire, au moins pas en C#. Un bogue-fixe variation de Thomas Levesque réponse est probablement aussi proche que vous obtiendrez.Voici le bug-version fixe de La réponse de Thomas:
Et voici comment j'allais le faire en C# si la collection n'expose pas de
Count
propriété et les éléments ne sont pas directement accessibles par un index. (Notez qu'il n'y a pasforeach
et le code n'est pas particulièrement succincte, mais elle donnera des performances décentes sur à peu près tout énumérable collection).Au moins en C# qui n'est pas possible sans un régulier pour la boucle.
L'agent recenseur de la collection qui décide si une prochaine éléments (méthode MoveNext), la boucle ne le sait pas.
Je pense que je préfère kgiannakakis's solution, cependant, vous pouvez toujours faire quelque chose comme cela;
J'ai remarqué un certain nombre de suggestions supposons que vous trouverez le dernier élément de la liste avant de commencer la boucle, puis de les comparer chaque élément de cet élément. Si vous pouvez le faire de manière efficace, les données sous-jacentes de la structure est probablement un simple tableau. Si c'est le cas, pourquoi s'embêter avec le foreach à tous? Il suffit d'écrire:
Si vous ne pouvez pas récupérer un élément à partir d'une position arbitraire de façon efficiente, comme la structure sous-jacente est une liste liée -- puis obtenir le dernier élément probablement impliqués d'une recherche séquentielle de l'ensemble de la liste. En fonction de la taille de la liste, qui peut être un problème de performance. Si c'est souvent exécutée fonction, vous pouvez envisager d'utiliser un tableau ou une liste de tableaux ou de structure comparable, de sorte que vous pouvez le faire de cette façon.
Me semble que vous êtes en train de demander, "Quel est le meilleur moyen pour mettre une vis à l'aide d'un marteau?", lorsque bien sûr, la meilleure question à se poser est "qu'est-Ce le bon outil à utiliser pour mettre une vis?"
Serait-il une solution viable pour votre cas il suffit de prendre la première/dernière éléments de votre tableau avant de faire le "général" chaque course?
Comme ceci:
Ce problème peut être résolu d'une manière élégante l'aide d'un patron dans un langage de programmation fonctionnel tel que F#:
Je ne sais pas comment les boucles for-each fonctionne dans d'autres langues, mais java.
En java pour chacun utilise le Itératif de l'interface qui est utilisée par le pour-chaque pour obtenir un Itérateur et boucle avec elle. Itérateur est une méthode hasNext que vous pouvez utiliser si vous pouviez voir l'itérateur à l'intérieur de la boucle.
Vous pouvez réellement faire le tour, en enfermant un déjà obtenu Itérateur dans un objet iterable objet de sorte que la boucle for a obtenu ce dont elle a besoin et vous pouvez obtenir une méthode hasNext l'intérieur de la boucle.
Vous pouvez créer une classe qui encapsule tout ce itérable et itérateur de choses donc le code ressemble à ceci:
Similaire à kgiannakakis réponse:
Comment à ce sujet? juste appris un peu de Ruby. hehehe
Supprimer le dernier de la liste et de conserver son avlue.
Un autre modèle qui fonctionne, sans avoir à les réécrire
foreach
boucle:De cette façon, le compilateur maintient la boucle de droite, les itérateurs (y compris ceux sans compte) fonctionnent comme prévu, et le dernier est séparé des autres.
J'utilise aussi ce modèle quand je veux quelque chose se passe dans entre les itérations, mais pas après la dernière. Dans ce cas,
X
est utilisé normalement,delayed
se réfère à quelque chose d'autre, et l'usage de retard est seulement au début de la boucle et rien ne doit être fait qu'après la boucle se termine.Utilisation
join
chaque fois que possible.Le plus souvent, le séparateur est la même entre tous les éléments, juste de se joindre à eux avec la fonction correspondante dans votre langue.
Ruby exemple,
Cela devrait couvrir 99% de tous les cas, et si pas diviser le tableau en tête et la queue.
Ruby exemple,
<hello>
que pensons-nous ici?Comme une modélisation de la notation, l'influence de l'OMT notation domine (e. g., en utilisant des rectangles pour les classes et les objets). Si le Booch "cloud" de la notation a été abandonné, les Booch capacité de spécifier le niveau inférieur des détails de conception a été adopté. Le cas d'utilisation de la notation de Objectory et la composant de la notation de Booch ont été intégrées avec le reste de la notation, mais la sémantique de l'intégration a été relativement faible dans UML 1.1, et n'était pas vraiment fixe jusqu'à ce que l'UML 2.0 révision majeure.