Ruby Language
Iteración
Buscar..
Cada
Ruby tiene muchos tipos de enumeradores, pero el primer y más simple tipo de enumerador para comenzar es each . Imprimiremos even o odd para cada número entre 1 y 10 para mostrar cómo funciona each .
Básicamente hay dos formas de pasar los llamados blocks . Un block es un fragmento de código que se pasa y se ejecutará mediante el método al que se llama. each método toma un block que llama a cada elemento de la colección de objetos a los que fue llamado.
Hay dos formas de pasar un bloque a un método:
Método 1: en línea
(1..10).each { |i| puts i.even? ? 'even' : 'odd' }
Esta es una forma muy comprimida y rubí de resolver esto. Vamos a desglosar pieza por pieza.
-
(1..10)es un rango de1a10inclusive. Si quisiéramos que fuera de1a10exclusiva, escribiríamos(1...10). -
.eaches un enumerador que enumeraeachelemento en el objeto sobre el que está actuando. En este caso, actúa sobreeachnúmero en el rango. -
{ |i| puts i.even? ? 'even' : 'odd' }es el bloque paraeachdeclaración, que a su vez se puede desglosar.-
|i|esto significa que cada elemento en el rango está representado dentro del bloque por el identificadori. -
putses un método de salida en Ruby que tiene un salto de línea automático cada vez que se imprime. (Podemos usarprintsi no queremos el salto de línea automático) -
i.even?comprueba siipar. También podríamos haber utilizadoi % 2 == 0; sin embargo, es preferible utilizar métodos incorporados. -
? "even" : "odd"es el operador ternario de ruby. ¿La forma en que se construye un operador ternario es laexpression ? a : b. Esto es corto para
if expression a else b end
-
Para el código más largo de una línea, el block debe pasar como un multiline block .
Método 2: multilínea
(1..10).each do |i|
if i.even?
puts 'even'
else
puts 'odd'
end
end
En un multiline block do reemplaza el soporte de apertura y el end reemplaza el soporte de cierre del estilo en inline .
Ruby soporta reverse_each también. Se itera la matriz hacia atrás.
@arr = [1,2,3,4]
puts @arr.inspect # output is [1,2,3,4]
print "Reversed array elements["
@arr.reverse_each do |val|
print " #{val} " # output is 4 3 2 1
end
print "]\n"
Implementación en una clase
Enumerable es el módulo más popular en Ruby. Su propósito es proporcionarle métodos iterables como map , select , reduce , etc. Las clases que usan Enumerable incluyen Array , Hash , Range . Para usarlo, debes include Enumerable e implementar each .
class NaturalNumbers
include Enumerable
def initialize(upper_limit)
@upper_limit = upper_limit
end
def each(&block)
0.upto(@upper_limit).each(&block)
end
end
n = NaturalNumbers.new(6)
n.reduce(:+) # => 21
n.select(&:even?) # => [0, 2, 4, 6]
n.map { |number| number ** 2 } # => [0, 1, 4, 9, 16, 25, 36]
Mapa
Devuelve el objeto modificado, pero el objeto original permanece como estaba. Por ejemplo:
arr = [1, 2, 3]
arr.map { |i| i + 1 } # => [2, 3, 4]
arr # => [1, 2, 3]
map! Cambia el objeto original:
arr = [1, 2, 3]
arr.map! { |i| i + 1 } # => [2, 3, 4]
arr # => [2, 3, 4]
Nota: también puedes usar la collect para hacer lo mismo.
Iterando sobre objetos complejos.
Arrays
Puede iterar sobre matrices anidadas:
[[1, 2], [3, 4]].each { |(a, b)| p "a: #{ a }", "b: #{ b }" }
La siguiente sintaxis también está permitida:
[[1, 2], [3, 4]].each { |a, b| "a: #{ a }", "b: #{ b }" }
Producirá:
"a: 1"
"b: 2"
"a: 3"
"b: 4"
Hashes
Puede iterar sobre pares clave-valor:
{a: 1, b: 2, c: 3}.each { |pair| p "pair: #{ pair }" }
Producirá:
"pair: [:a, 1]"
"pair: [:b, 2]"
"pair: [:c, 3]"
Puede iterar sobre claves y valores simultáneamente:
{a: 1, b: 2, c: 3}.each { |(k, v)| p "k: #{ k }", "v: #{ k }" }
Producirá:
"k: a"
"v: a"
"k: b"
"v: b"
"k: c"
"v: c"
Para iterador
Esto se repite de 4 a 13 (inclusive).
for i in 4..13
puts "this is #{i}.th number"
end
También podemos iterar sobre matrices usando para
names = ['Siva', 'Charan', 'Naresh', 'Manish']
for name in names
puts name
end
Iteración con índice
A veces desea saber la posición ( índice ) del elemento actual mientras se repite en un enumerador. Para tal fin, Ruby proporciona el método with_index . Se puede aplicar a todos los enumeradores. Básicamente, al agregar with_index a una enumeración, puede enumerar esa enumeración. El índice se pasa a un bloque como segundo argumento.
[2,3,4].map.with_index { |e, i| puts "Element of array number #{i} => #{e}" }
#Element of array number 0 => 2
#Element of array number 1 => 3
#Element of array number 2 => 4
#=> [nil, nil, nil]
with_index tiene un argumento opcional: el primer índice es 0 por defecto:
[2,3,4].map.with_index(1) { |e, i| puts "Element of array number #{i} => #{e}" }
#Element of array number 1 => 2
#Element of array number 2 => 3
#Element of array number 3 => 4
#=> [nil, nil, nil]
Hay un método específico each_with_index . La única diferencia entre él y cada uno. Con each.with_index es que no puede pasarle un argumento a eso, por lo que el primer índice es 0 todo el tiempo.
[2,3,4].each_with_index { |e, i| puts "Element of array number #{i} => #{e}" }
#Element of array number 0 => 2
#Element of array number 1 => 3
#Element of array number 2 => 4
#=> [2, 3, 4]