Jeśli mam pętlę, taką jak
users.each do |u|
#some code
end
Gdzie użytkownicy to skrót wielu użytkowników. Jaka jest najłatwiejsza logika warunkowa, aby sprawdzić, czy jesteś na ostatnim użytkowniku w skrócie użytkowników i chcesz wykonać tylko określony kod dla tego ostatniego użytkownika, więc coś w rodzaju
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
źródło
źródło
each_with_index
anilast
metod.Hash
miesza się w Enumerable, więc maeach_with_index
. Nawet jeśli klucze haszujące nie są posortowane, ten rodzaj logiki pojawia się cały czas podczas renderowania widoków, gdzie ostatni element może być wyświetlany inaczej, niezależnie od tego, czy jest to faktycznie „ostatni” w jakimkolwiek sensie danych.each_with_index
, przepraszam. Tak, widzę, że wyjdzie; próbuję tylko wyjaśnić pytanie. Osobiście najlepszą odpowiedzią dla mnie jest użycie,.last
ale to nie dotyczy tylko tablicy.Odpowiedzi:
users.each_with_index do |u, index| # some code if index == users.size - 1 # code for the last user end end
źródło
.last
poza pętlą.users.each_with_index do |(key, value), index| #your code end
Jeśli jest to sytuacja typu „albo / albo”, w której stosujesz kod do wszystkich użytkowników oprócz ostatniego, a następnie jakiś unikalny kod tylko do ostatniego użytkownika, jedno z pozostałych rozwiązań może być bardziej odpowiednie.
Wydaje się jednak, że uruchamiasz ten sam kod dla wszystkich użytkowników i dodatkowy kod dla ostatniego użytkownika. Jeśli tak jest, wydaje się to bardziej poprawne i jaśniej określa twój zamiar:
users.each do |u| #code for everyone end users.last.do_stuff() # code for last user
źródło
.last
które nie ma nic wspólnego z zapętleniem..last
. Kolekcja została już utworzona, to tylko prosty dostęp do tablicy. Nawet jeśli kolekcja nie została jeszcze załadowana (tak jak w przypadku, nadal była to nieuwodniona relacja ActiveRecord)last
nadal nigdy nie wykonuje pętli w celu uzyskania ostatniej wartości, byłoby to szalenie nieefektywne. Po prostu modyfikuje zapytanie SQL, aby zwrócić ostatni rekord. To powiedziawszy, ta kolekcja została już załadowana przez.each
, więc nie ma większej złożoności niż gdybyś to zrobiłx = [1,2,3]; x.last
.Myślę, że najlepszym podejściem jest:
users.each do |u| #code for everyone if u.equal?(users.last) #code for the last user end end
źródło
u.equal?(users.last)
,equal?
metoda porównuje object_id, a nie wartość obiektu. Ale to nie zadziała z symbolami i liczbami.Czy próbowałeś
each_with_index
?users.each_with_index do |u, i| if users.size-1 == i #code for last items end end
źródło
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
źródło
Czasami wydaje mi się, że lepiej rozdzielić logikę na dwie części, jedną dla wszystkich użytkowników i drugą dla ostatniej. Więc zrobiłbym coś takiego:
users[0...-1].each do |user| method_for_all_users user end method_for_all_users users.last method_for_last_user users.last
źródło
Możesz użyć podejścia @ meager również w sytuacji albo / albo, gdy stosujesz kod do wszystkich użytkowników oprócz ostatniego, a następnie unikalny kod tylko do ostatniego użytkownika.
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
W ten sposób nie potrzebujesz warunku!
źródło
users[0..-2]
jest poprawne, jak jestusers[0...-1]
. Zwróć uwagę na różne operatory zakresu w..
porównaniu z...
, patrz stackoverflow.com/a/9690992/67834Innym rozwiązaniem jest uratowanie przed StopIteration:
user_list = users.each begin while true do user = user_list.next user.do_something end rescue StopIteration user.do_something end
źródło
StopIteration
jest zaprojektowany z konkretnego powodu obsługi wyjść pętli. Z książki Matza: „Może się to wydawać niezwykłe - wyjątek jest zgłaszany raczej dla oczekiwanego warunku zakończenia, a nie dla nieoczekiwanego i wyjątkowego zdarzenia. (StopIteration
Jest potomkiemStandardError
iIndexError
; zauważ, że jest to jedna z jedynych klas wyjątków, która nie zawiera słowa „Błąd” w nazwie.) Ruby podąża za Pythonem w tej zewnętrznej technice iteracji. (Więcej ...)next
przez specjalną wartość końca iteracji i nie ma potrzeby wywoływania jakiegośnext?
predykatu przed wywołaniemnext
. ”loop do
posiada ukryterescue
przy spotkaniu zStopIteration
; jest szczególnie używany podczas zewnętrznej iteracjiEnumerator
obiektu.loop do; my_enum.next; end
dokona iteracjimy_enum
i zakończy na końcu; nie ma potrzeby umieszczaniarescue StopIteration
tam. (Musisz, jeśli używaszwhile
lubuntil
.)W przypadku niektórych wersji języka Ruby nie ma ostatniej metody obliczania skrótu
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
źródło
last
, zestaw kluczy będzie nieuporządkowany, więc ta odpowiedź i tak zwróci błędne / losowe wyniki.