Arrays en Ruby
Publicado el Miércoles, 21 de septiembre de 2011Hoy voy a compartir mis apuntes sobre Arrays en Ruby. Como comentaba en posts anteriores, vengo estudiando con el libro Programming Ruby 1.9: The Pragmatic Programmers' Guide. Vengo acompañando la lectura con los Ruby Koans, y algunos video tutoriales. Ya repasé lo de Rails For Zombies, y descubrí otro excelente recurso que son los RailsCasts. Vamos a ver si en algún momento tenemos algo escrito en Ruby para compartir 🙂
Vamos entonces con estructuras de datos de Ruby. Los Arrays y Hashes son dos clases creadas para el manejo de colecciones:
La maestría en estas dos clases es clave para ser un programador Ruby efectivo. Esta maestría puede llevar tiempo, porque ambas clases tienen interfaces muy grandes.
Teniendo en cuenta esta cita del libro, veamos una definición bien específica de qué es un Array en Ruby:
- Arrays
- Colección de referencias a objetos.
En Ruby, las variables guardan la referencia a un objeto, y no el objeto en sí. Cada referencia a un objeto ocupa una posición en el array identificado por un índice entero.
a = [3.141592, "pi", 42] a.class # Array a.length # 3 a[0] # 3.141592 a[2] # 42 a[3] # nil a[15] # nil b = Array.new b.class # Array b.length # 0 b[0] = "Uno" b[1] = "Dos" b # ["Uno", "Dos"] |
Se indexan los elementos usando el operador []
, un método de instancia de la clase Array que puede ser sobrescrito. Llamar a una posición de un entero positivo, retorna el objeto en ese lugar o nil
si no hay nada ahí. Con los índices negativos, se cuenta desde el final siendo -1 el último elemento del array, y -array.length el primero.
a = [1, 5, 6, 38, 95] # 0, 1, 2, 3, 4 índices positivos # -5, -4, -3, -2, -1 índices negativos a[-1] # 95 a[-3] # 6 a[-56] # nil |
Se pueden indexar con un par de números (inicio, cantidad). Esto devuelve un nuevo array con referencias a la cantidad de objetos comenzando en la posición inicio.
a = [1, 5, 6, 38, 95] a[1,3] # [5, 6, 38] a[-3, 2] # [6, 38] |
También se pueden usar rangos. Ruby implementa un objeto para representar rangos como los meses de Enero a Diciembre, secuencias de números y demás. En el caso de los arrays, se usan los rangos que implementan secuencias (también implementan condiciones e intervalos). Estos funcionan así:
1..10 1...10 |
Cuando se usan los tres puntos, se excluye al último elemento del rango.
De esta manera, podemos acceder a los elementos de un array así:
a = [1, 5, 6, 38, 95] a[1..3] # [5, 6, 38] a[-4..4] # [5, 6, 38, 95] |
El operador []
tiene un operador []=
para setear elementos en el array. Si se usa un solo índice entero, el elemento en esa posición se reemplaza con lo que haya a la derecha de la asignación. Si quedan espacios sin asignar en el medio, estos se llenan con nil.
a = [1, 5, 6, 38, 95] a[1] = 'Stegosaurus' #[1, 'Stegosaurus', 6, 38, 95] a[3] = [5, 6] #[1, 'Stegosaurus', 6, [5, 6], 95] a[6] = 99 #[1, 'Stegosaurus', 6, [5, 6], 95. nil, 99] |
Si el índice de la asignación []= son dos números(un inicio y longitud) o un rango, los dos elementos en el array original son reemplazados por lo que haya a la derecha de la asignación.
a = [1, 5, 6, 38, 95] a[2,2] = 'Velociraptor' #[1, 5, 'Velociraptor', 95] #Si la longitud es 0, se inserta el valor de la derecha antes de la posición de inicio a[2,0] = 'Nintendo 64' #[1, 5, 'Nintendo 64', 'Velociraptor', 95] #Si el valor a asignar es un array, se usan sus elementos en la asignación a[1,1] = [4, 7, 82] #[1, 4, 7, 82, 'Nintendo 64', 'Velociraptor', 95] a[0..3] = [] #['Nintendo 64', 'Velociraptor', 95] a[5..6] = 'AYBABTU', 98 #['Nintendo 64', 'Velociraptor', 95, nil, nil, 'AYBABTU', 98] |
Arrays como pilas y colas
Los arrays implementan las funciones push
y pop
que agregan y quitan elementos al final del array, por lo que pueden ser usados como pilas (stack):
pila = [] pila.push "Leonardo" pila.push "Donatello" pila.push "Raphael" pila.push "Michelangelo" puts pila.pop # Michelangelo puts pila.pop # Raphael p pila # ["Leonardo", "Donatello"] |
Los métodos shift
y unshift
agregan y quitan elementos del principio del Array. Combinando ambos obtenemos una cola FIFO:
cola = [] cola.push "Leonardo" cola.push "Donatello" puts cola.shift puts cola.shift |
En este código, los elementos se quitan del array en el orden que fueron insertados. Está bueno ir escribiendo todo esto en el shell interactivo de Ruby (irb), el cual debería estar instalado en su sistema si instalaron Ruby. De esa forma pueden ir comprobando los resultados esperados de cada método y demás.
Otra opción es usar los métodos first
y last
. Éstos devuelven los elementos pero sin quitarlos del array. Se puede pasar como parámetro la cantidad de elementos que queremos recibir.
Más info:
- La clase Array en RubyDoc - http://www.ruby-doc.org/core/classes/Array.html
Deleteman 21 septiembre. 2011 - 11:16
Muy bueno el articulo, cubre la base de los arrays muy bien!
Un pique sobre arrays (que va de la mano con la asignación en paralelo) es que podés separar un array en head y tail (“ala” programación funcional) bien fácil, haciendo (por lo menos en ruby 1.9.2):
Te queda head = 1 y tail = [2,3,4,5], así podés hacer cosas como:
Y ahí podés llamar a, por ejemplo: sum (1..1000).to_a y te hace la suma super rápido.
Da para chiviar un poco con recursión 🙂
Fernando 22 septiembre. 2011 - 10:27
¡Gracias por el comentario! Modifiqué un poco el comentario para darle formato (acá hay más info de cómo hacerlo).
Voy a jugar un rato con el código que aportaste, ¡gracias por el pique! Es el tipo de aportes que busco con estos posts 🙂
Liber Dovat 21 septiembre. 2011 - 11:55
Muy bueno el tutorial!!
Ahora, una duda.
En el ejemplo de a = [3.141592, “pi”, 42] decís que a[3] vale 42, pero no sería a[2]?
Pregunto porque en realidad no sé como funciona ruby 🙂
Fernando 21 septiembre. 2011 - 13:11
Uh, fue un error en el código. Ya quedó corregido en el post. Como en los demás lenguajes, los Arrays empiezan en 0, así que a[3] no tenía elementos.
¡Gracias por el comentario!
Liber Dovat 21 septiembre. 2011 - 14:12
Ah, dale.
Clarísimo entonces.
Digamos que es un lenguaje como los de verdad.
Fernando 22 septiembre. 2011 - 10:31
Ruby es un Señor Lenguaje 😛
M 27 septiembre. 2011 - 23:38
Muy bueno!!
Che podrías hacerte unos tutoriales de Android también no? 😛
Fernando 28 septiembre. 2011 - 19:56
¡Gracias!
No he tocado Android en un buen tiempo, pero no estaría mal armar algo. Tengo ganas de probar algo en Android. Por ahora vengo estudiando intensivamente Ruby, pero ni bien meta mano en Android nuevamente, ¡lo publico!
Saludos
Fabian Astorgan 24 diciembre. 2012 - 12:37
Hola, estoy empezando en ruby..te hago una consulta a ver sime podes dar una mano.
Necesito leer un archivo de texto y asignar cada linea a una variable distinta. Tengo una forma de resolver, pero es poco ortodoxa y ya que estoy aprendiendo quiero hacerlo bien.. mi idea (la que no funciona) seria asi:
el con tenido del archivo supongamos:
JUAN
PEDRO
PABLO
File.read(archivo).each_line { | line | #leo el archivo
vector = [“#{archive}”,”#{archive}”,”#{archive}”]# esta es la parte que no se.. la idea seria asignar cada linea en una matriz
@variable1 = vector[0] # juan
@variable2 = vector[1] # pedro
…
No se si estoy mezclando peras con pepinos.. si mepodes dar una mano te lo agradesco.. Saludos
Fernando 25 mayo. 2013 - 06:25
Fabian,
Si entendí bien la pregunta, la cosa sería así:
Fabian Astorgan 24 diciembre. 2012 - 12:38
Perdon, en vector donde dice “#{archive}” deberia ser “#{line}” je
Matias 21 julio. 2015 - 15:30
como agregar varios datos en una matriz despues de un enter, se entiende??
EJ: Yo quiero agregar una palabra, y al rato quiero agregar otra palabra y despues se me ocurre agregar otra palabra…. Esto tendria que ser en lineas diferentes y interactuando con el programa.
En teoria los datos que uno agrega tiene que estar guardados en la matriz y si yo llamo a esa matriz tiene que devolver los datos que se guardaron!!!
Fernando 21 julio. 2015 - 19:08
Hola Matías,
Para agregar elementos a una matriz hay que usar el operador
<<
opush
. Ejemplo:Capaz que debería agregarlo al post si no quedó muy claro. ¡Saludos!
Ale 14 abril. 2016 - 09:24
Hola. Si tengo un array de cinco posiciones Ejemplo. a [1,2,3,4,5] quiero eliminar la posicion 3. Como lo haria?
Gracias
Fernando 28 abril. 2016 - 13:43
Hola Ale,
Para eliminar el elemento de una posición se puede usar el método
delete_at
:Cielo 26 septiembre. 2017 - 15:41
def medicinaMasVendida(tipos, ventas)
end
medicinaMasVendida([“amex”,”esitol”,”jaditor”,”rubicol”,”zainex”], [1000,1200,600,400,500])
si tengo este array como hago que me regrese la medicina mas vendida?
Fernando 26 septiembre. 2017 - 16:49
Hola Cielo,
Los datos de los dos arrays no están relacionados. Si fuera un hash de este estilo:
Ahí podrías usar un método de Enumerable para encontrar el que tenga mayor valor.