Decir el final de un bucle. each en ruby


Si tengo un bucle como

users.each do |u|
  #some code
end

Donde usuarios es un hash de múltiples usuarios. ¿Cuál es la lógica condicional más fácil de ver si está en el último usuario en el hash de usuarios y solo desea ejecutar código específico para ese último usuario, por lo que algo como

users.each do |u|
  #code for everyone
  #conditional code for last user
    #code for the last user
  end
end

Gracias

Author: Wouter J, 2010-10-23

9 answers

users.each_with_index do |u, index|
  # some code
  if index == users.size - 1
    # code for the last user
  end
end
 126
Author: Raphomet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-22 20:34:25

Si se trata de una situación en la que se aplica algún código a todos pero el último usuario y luego algún código único a solo el último usuario, una de las otras soluciones podría ser más apropiada.

Sin embargo, parece que está ejecutando el mismo código para todos los usuarios, y algo de código adicional para el último usuario. Si ese es el caso, esto parece más correcto, y más claramente establece su intención:

users.each do |u|
  #code for everyone
end

users.last.do_stuff() # code for last user
 36
Author: meagar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-22 20:39:58

Creo que un mejor enfoque es:

users.each do |u|
  #code for everyone
  if u.equal?(users.last)
    #code for the last user
  end
end
 18
Author: Alter Lagos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-12 15:03:57

¿Lo intentaste each_with_index?

users.each_with_index do |u, i|
  if users.size-1 == i
     #code for last items
  end
end
 9
Author: Teja Kantamneni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-22 20:35:35
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
 6
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-22 20:38:42

A veces me parece mejor separar la lógica en dos partes, una para todos los usuarios y otra para la última. Así que haría algo como esto:

users[0...-1].each do |user|
  method_for_all_users user
end

method_for_all_users users.last
method_for_last_user users.last
 3
Author: xlembouras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-30 09:07:33

Puede usar el enfoque de @meager también para una situación de cualquiera/o, donde está aplicando algún código a todos menos al último usuario y luego un código único solo al último usuario.

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 esta manera no necesitas un condicional!

 3
Author: coderuby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-16 13:34:44

Otra solución es rescatar de la StopIteration:

user_list = users.each

begin
  while true do
    user = user_list.next
    user.do_something
  end
rescue StopIteration
  user.do_something
end
 1
Author: ricardokrieg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-11 00:15:06

No hay un último método para hash para algunas versiones 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
 0
Author: Sathianarayanan Sundaram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-23 07:06:19