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 de1
a10
inclusive. Si quisiéramos que fuera de1
a10
exclusiva, escribiríamos(1...10)
. -
.each
es un enumerador que enumeraeach
elemento en el objeto sobre el que está actuando. En este caso, actúa sobreeach
número en el rango. -
{ |i| puts i.even? ? 'even' : 'odd' }
es el bloque paraeach
declaració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
. -
puts
es un método de salida en Ruby que tiene un salto de línea automático cada vez que se imprime. (Podemos usarprint
si no queremos el salto de línea automático) -
i.even?
comprueba sii
par. 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]