2011-01-04 9 views
8

¿Hay alguna forma de encontrar el siguiente elemento en una matriz de Ruby?Ruby encuentra el siguiente en la matriz

Código:

# Find ALL languages 
if !debug 
    lang = Language.all 
else 
    lang = Language.where("id = ? OR id = ?", 22, 32) 
end 

# Get all elements 
elements = Element.where("human_readable IS NOT NULL") 

lang.each do |l| 
    code = l.code.downcase 
    if File.exists?(file_path + code + ".yml") 
    File.delete(file_path + code + ".yml") 
    end 

    t1 = Time.now 

    info = {} 
    elements.each do |el| 
    unless l.id == 1 
     et = el.element_translations.where("language_id = ? AND complete = ?", l.id, true) 
    else 
     et = el.element_translations.where("language_id = ?", 1) 
    end 
    et.each do |tran| 
     info[code] ||= {} 
     info[code][el.human_readable] = tran.content.gsub("\n", "").force_encoding("UTF-8").encode! 
    end 
    end 
    File.open(file_path + code + ".yml", "w", :encoding => "UTF-8") do |f| 
    if f.write(info.to_yaml) 
     t2 = Time.now 

     puts code + ".yml File written" 
     puts "It took " + time_diff_milli(t1, t2).to_s + " seconds to complete" 
     # This is where I want to display the next item in the lang array 
     puts lang.shift(1).inspect 
     puts "*"*50 
    end 
    end 
end 
+4

¿Después de qué? – marcog

+0

Código de trabajo está por encima de – dennismonsewicz

+0

Tenga cuidado 'pone lang.shift (1) .inspect', usando eso dentro de un bloque iterando sobre lang podría causar algunos problemas. Entonces de nuevo, tal vez no. –

Respuesta

28

Array incluye Enumerable, para que pueda utilizar each_with_index:

elements.each_with_index {|element, index| 
    next_element = elements[index+1] 
    do_something unless next_element.nil? 
    ... 

} 
+0

+1 Se requieren algunos ajustes para obtener exactamente lo que desea el OP, pero una buena descripción general del enfoque correcto –

+0

¡Gracias por la ayuda! – dennismonsewicz

+1

Creo que se proponía poner 'do_something unless next_element.nil?' – Noz

26

Una buena manera de iterar sobre una Enumerable si necesita acceder a un elemento y el siguiente está usando each_cons:

arr = [1, 2, 3] 
arr.each_cons(2) do |element, next_element| 
    p "#{element} is followed by #{next_element}" 
    #... 
end 

# => "1 is followed by 2", "2 is followed by 3". 

Según lo señalado por Phrogz, Enumerable#each_cons está disponible en Ruby 1.8.7+; para Ruby 1.8.6 puede require 'backports/1.8.7/enumerable/each_cons'.

Como señala @Jacob, el otro enfoque es usar each_with_index.

+0

Para el registro, 'each_cons' solo está disponible en 1.8.7+ (no en 1.8.6). – Phrogz

+0

@Phrogz: ¡De hecho! Yo soy el que generalmente lo señala. Respuesta actualizada –

2

Sobre la base de Marc-Andrés respuesta agradable Quiero dar una respuesta que, de forma genérica, da el siguiente elemento de todos elementos, también el último, por el relleno con nil:

arr = [1, 2, 3] 
[arr, nil].flatten.each_cons(2) do |element, next_element| 
    p "#{element} is followed by #{next_element || 'nil'}" 
end 

# "1 is followed by 2" 
# "2 is followed by 3" 
# "3 is followed by nil" 

Ahora, mientras estamos en ello, también podemos proporcionar el elemento anterior para todos los elementos:

arr = [1, 2, 3] 
[nil, arr, nil].flatten.each_cons(3) do |prev_element, element, next_element| 
    p "#{element} is preceded by #{prev_element || 'nil'} and followed by #{next_element || 'nil'}" 
end 

# "1 is preceded by nil and followed by 2" 
# "2 is preceded by 1 and followed by 3" 
# "3 is preceded by 2 and followed by nil" 
Cuestiones relacionadas