Si j'ai une boucle telle que
users.each do |u|
#some code
end
Où utilisateurs est un hachage de plusieurs utilisateurs. Quelle est la logique conditionnelle la plus simple pour voir si vous êtes sur le dernier utilisateur dans le hachage des utilisateurs et que vous souhaitez uniquement exécuter du code spécifique pour ce dernier utilisateur, donc quelque chose comme
users.each do |u|
#code for everyone
#conditional code for last user
#code for the last user
end
end
ruby-on-rails
ruby
loops
each
Splashlin
la source
la source
each_with_index
nilast
méthodes.Hash
se mélange dans Enumerable, donc c'est le caseach_with_index
. Même si les clés de hachage ne sont pas triées, ce type de logique apparaît tout le temps lors du rendu des vues, où le dernier élément peut être affiché différemment, qu'il soit réellement "dernier" dans un sens significatif pour les données.each_with_index
excuses. Oui, je peux voir que cela arriverait; essayant juste de clarifier la question. Personnellement, la meilleure réponse pour moi est l'utilisation de.last
mais cela ne s'applique pas pour un hachage uniquement un tableau.Réponses:
users.each_with_index do |u, index| # some code if index == users.size - 1 # code for the last user end end
la source
.last
dehors de la boucle.users.each_with_index do |(key, value), index| #your code end
S'il s'agit d'une situation soit / ou, où vous appliquez du code à tous sauf le dernier utilisateur, puis un code unique uniquement au dernier utilisateur, l'une des autres solutions pourrait être plus appropriée.
Cependant, vous semblez exécuter le même code pour tous les utilisateurs et du code supplémentaire pour le dernier utilisateur. Si tel est le cas, cela semble plus correct et indique plus clairement votre intention:
users.each do |u| #code for everyone end users.last.do_stuff() # code for last user
la source
.last
qui n'ont rien à voir avec la boucle..last
. La collection est déjà instanciée, c'est juste un simple accès à un tableau. Même si la collection n'avait pas déjà été chargée (comme dans, c'était toujours une relation ActiveRecord non hydratée)last
ne boucle toujours jamais pour obtenir la dernière valeur, ce serait extrêmement inefficace. Il modifie simplement la requête SQL pour renvoyer le dernier enregistrement. Cela dit, cette collection a déjà été chargée par le.each
, il n'y a donc pas plus de complexité que si vous l'aviez faitx = [1,2,3]; x.last
.Je pense qu'une meilleure approche est:
users.each do |u| #code for everyone if u.equal?(users.last) #code for the last user end end
la source
u.equal?(users.last)
, laequal?
méthode compare object_id, pas la valeur de l'objet. Mais cela ne fonctionnera pas avec les symboles et les nombres.Avez-vous essayé
each_with_index
?users.each_with_index do |u, i| if users.size-1 == i #code for last items end end
la source
h = { :a => :aa, :b => :bb } h.each_with_index do |(k,v), i| puts ' Put last element logic here' if i == h.size - 1 end
la source
Parfois, je trouve préférable de séparer la logique en deux parties, une pour tous les utilisateurs et une pour la dernière. Donc je ferais quelque chose comme ça:
users[0...-1].each do |user| method_for_all_users user end method_for_all_users users.last method_for_last_user users.last
la source
Vous pouvez également utiliser l'approche de @ maigre pour une situation soit / ou, où vous appliquez du code à tous sauf le dernier utilisateur, puis un code unique au dernier utilisateur.
users[0..-2].each do |u| #code for everyone except the last one, if the array size is 1 it gets never executed end users.last.do_stuff() # code for last user
De cette façon, vous n'avez pas besoin d'un conditionnel!
la source
users[0..-2]
est correct, tel quelusers[0...-1]
. Notez les différents opérateurs de plage..
vs...
, voir stackoverflow.com/a/9690992/67834Une autre solution consiste à récupérer de StopIteration:
user_list = users.each begin while true do user = user_list.next user.do_something end rescue StopIteration user.do_something end
la source
StopIteration
est conçu pour la raison précise de gérer les sorties de boucle. Extrait du livre de Matz: "Cela peut sembler inhabituel - une exception est levée pour une condition de terminaison attendue plutôt qu'un événement inattendu et exceptionnel. (StopIteration
Est un descendant deStandardError
etIndexError
; notez que c'est l'une des seules classes d'exception qui n'a pas le mot «Erreur» dans son nom.) Ruby suit Python dans cette technique d'itération externe. (next
pour une valeur de fin d'itération spéciale, et il n'est pas nécessaire d'appeler une sorte denext?
prédicat avant d'appelernext
. "loop do
a un impliciterescue
lors de la rencontre d'unStopIteration
; il est spécifiquement utilisé lors de l'itération externe d'unEnumerator
objet.loop do; my_enum.next; end
va itérermy_enum
et quitter à la fin; pas besoin de mettre unrescue StopIteration
là dedans. (Vous devez le faire si vous utilisezwhile
ouuntil
.)Il n'y a pas de dernière méthode de hachage pour certaines versions de ruby
h = { :a => :aa, :b => :bb } last_key = h.keys.last h.each do |k,v| puts "Put last key #{k} and last value #{v}" if last_key == k end
la source
last
, l'ensemble de clés ne sera pas ordonné, donc cette réponse renverra de toute façon des résultats erronés / aléatoires.