Ruby Language
Arrays
Buscar..
Sintaxis
- a = [] # usando literal de matriz
- a = Array.new # equivalente a usar literal
- a = Array.new (5) # crea una matriz con 5 elementos con valor nil.
- a = Array.new (5, 0) # crea una matriz con 5 elementos con un valor predeterminado de 0.
#mapa
#map
, proporcionado por Enumerable, crea una matriz invocando un bloque en cada elemento y recolectando los resultados:
[1, 2, 3].map { |i| i * 3 }
# => [3, 6, 9]
['1', '2', '3', '4', '5'].map { |i| i.to_i }
# => [1, 2, 3, 4, 5]
La matriz original no se modifica; se devuelve una nueva matriz que contiene los valores transformados en el mismo orden que los valores de origen. map!
Se puede utilizar si desea modificar la matriz original.
En el método de map
, puede llamar al método o usar proc para todos los elementos de la matriz.
# call to_i method on all elements
%w(1 2 3 4 5 6 7 8 9 10).map(&:to_i)
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# using proc (lambda) on all elements
%w(1 2 3 4 5 6 7 8 9 10).map(&->(i){ i.to_i * 2})
# => [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
map
es sinónimo de collect
.
Creando un Array con el constructor literal []
Las matrices se pueden crear al incluir una lista de elementos entre corchetes ( [
y ]
). Los elementos de matriz en esta notación están separados por comas:
array = [1, 2, 3, 4]
Las matrices pueden contener cualquier tipo de objetos en cualquier combinación sin restricciones de tipo:
array = [1, 'b', nil, [3, 4]]
Crear matriz de cuerdas
Las matrices de cadenas se pueden crear utilizando la sintaxis de cadena de porcentaje de ruby:
array = %w(one two three four)
Esto es funcionalmente equivalente a definir la matriz como:
array = ['one', 'two', 'three', 'four']
En lugar de %w()
puede usar otros pares de delimitadores coincidentes: %w{...}
, %w[...]
o %w<...>
.
También es posible utilizar delimitadores no alfanuméricos arbitrarios, tales como: %w!...!
, %w#...#
o %w@...@
.
Se puede usar %W
lugar de %w
para incorporar la interpolación de cadenas. Considera lo siguiente:
var = 'hello'
%w(#{var}) # => ["\#{var}"]
%W(#{var}) # => ["hello"]
Se pueden interpretar varias palabras al escapar del espacio con una \.
%w(Colorado California New\ York) # => ["Colorado", "California", "New York"]
Crear matriz de símbolos
array = %i(one two three four)
Crea la matriz [:one, :two, :three, :four]
.
En lugar de %i(...)
, puede usar %i{...}
o %i[...]
o %i!...!
Además, si desea usar interpolación, puede hacer esto con %I
a = 'hello'
b = 'goodbye'
array_one = %I(#{a} #{b} world)
array_two = %i(#{a} #{b} world)
Crea las matrices: array_one = [:hello, :goodbye, :world]
array_two = [:"\#{a}", :"\#{b}", :world]
array_one = [:hello, :goodbye, :world]
y array_two = [:"\#{a}", :"\#{b}", :world]
Crear Array con Array :: nuevo
Se puede crear una matriz vacía ( []
) con el método de clase de la Array::new
, Array::new
:
Array.new
Para establecer la longitud de la matriz, pase un argumento numérico:
Array.new 3 #=> [nil, nil, nil]
Hay dos formas de rellenar una matriz con valores predeterminados:
- Pase un valor inmutable como segundo argumento.
- Pasa un bloque que obtiene el índice actual y genera valores mutables.
Array.new 3, :x #=> [:x, :x, :x]
Array.new(3) { |i| i.to_s } #=> ["0", "1", "2"]
a = Array.new 3, "X" # Not recommended.
a[1].replace "C" # a => ["C", "C", "C"]
b = Array.new(3) { "X" } # The recommended way.
b[1].replace "C" # b => ["X", "C", "X"]
Manipular elementos de matriz
Añadiendo elementos:
[1, 2, 3] << 4
# => [1, 2, 3, 4]
[1, 2, 3].push(4)
# => [1, 2, 3, 4]
[1, 2, 3].unshift(4)
# => [4, 1, 2, 3]
[1, 2, 3] << [4, 5]
# => [1, 2, 3, [4, 5]]
Eliminando elementos:
array = [1, 2, 3, 4]
array.pop
# => 4
array
# => [1, 2, 3]
array = [1, 2, 3, 4]
array.shift
# => 1
array
# => [2, 3, 4]
array = [1, 2, 3, 4]
array.delete(1)
# => 1
array
# => [2, 3, 4]
array = [1,2,3,4,5,6]
array.delete_at(2) // delete from index 2
# => 3
array
# => [1,2,4,5,6]
array = [1, 2, 2, 2, 3]
array - [2]
# => [1, 3] # removed all the 2s
array - [2, 3, 4]
# => [1] # the 4 did nothing
Combinando matrices:
[1, 2, 3] + [4, 5, 6]
# => [1, 2, 3, 4, 5, 6]
[1, 2, 3].concat([4, 5, 6])
# => [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6] - [2, 3]
# => [1, 4, 5, 6]
[1, 2, 3] | [2, 3, 4]
# => [1, 2, 3, 4]
[1, 2, 3] & [3, 4]
# => [3]
También puede multiplicar matrices, por ejemplo
[1, 2, 3] * 2
# => [1, 2, 3, 1, 2, 3]
Arreglos de unión, intersección y diferencia.
x = [5, 5, 1, 3]
y = [5, 2, 4, 3]
Union ( |
) contiene elementos de ambas matrices, con duplicados eliminados:
x | y
=> [5, 1, 3, 2, 4]
La intersección ( &
) contiene elementos que están presentes tanto en la primera como en la segunda matriz:
x & y
=> [5, 3]
La diferencia ( -
) contiene elementos que están presentes en la primera matriz y no están presentes en la segunda matriz:
x - y
=> [1]
Matrices de filtrado
A menudo queremos operar solo con elementos de una matriz que cumplan una condición específica:
Seleccionar
Devolverá elementos que coincidan con una condición específica.
array = [1, 2, 3, 4, 5, 6]
array.select { |number| number > 3 } # => [4, 5, 6]
Rechazar
Devolverá elementos que no coincidan con una condición específica.
array = [1, 2, 3, 4, 5, 6]
array.reject { |number| number > 3 } # => [1, 2, 3]
Tanto #select
como #reject
devuelven una matriz, por lo que se pueden encadenar:
array = [1, 2, 3, 4, 5, 6]
array.select { |number| number > 3 }.reject { |number| number < 5 }
# => [5, 6]
Inyectar, reducir
Inyectar y reducir son nombres diferentes para la misma cosa. En otros idiomas, estas funciones a menudo se llaman pliegues (como foldl o foldr). Estos métodos están disponibles en cada objeto Enumerable.
Inject toma una función de dos argumentos y la aplica a todos los pares de elementos en el Array.
Para la matriz [1, 2, 3]
podemos agregar todo esto junto con el valor de inicio de cero especificando un valor de inicio y un bloque de este modo:
[1,2,3].reduce(0) {|a,b| a + b} # => 6
Aquí pasamos a la función un valor inicial y un bloque que dice que se agreguen todos los valores. El bloque se ejecuta primero con 0
como a
y 1
como b
, luego toma el resultado de eso como el siguiente a
por lo que estamos agregando 1
al segundo valor 2
. Luego tomamos el resultado de eso ( 3
) y lo agregamos al elemento final de la lista (también 3
) que nos da el resultado ( 6
).
Si omitimos el primer argumento, se establece a
a ser el primer elemento de la lista, por lo que el ejemplo anterior es lo mismo que:
[1,2,3].reduce {|a,b| a + b} # => 6
Además, en lugar de pasar un bloque con una función, podemos pasar una función nombrada como un símbolo, ya sea con un valor de inicio o sin él. Con esto, el ejemplo anterior podría escribirse como:
[1,2,3].reduce(0, :+) # => 6
u omitiendo el valor inicial:
[1,2,3].reduce(:+) # => 6
Elementos de acceso
Puede acceder a los elementos de una matriz por sus índices. La numeración del índice de matriz comienza en 0
.
%w(a b c)[0] # => 'a'
%w(a b c)[1] # => 'b'
Puedes recortar una matriz usando el rango
%w(a b c d)[1..2] # => ['b', 'c'] (indices from 1 to 2, including the 2)
%w(a b c d)[1...2] # => ['b'] (indices from 1 to 2, excluding the 2)
Esto devuelve una nueva matriz, pero no afecta al original. Ruby también apoya el uso de índices negativos.
%w(a b c)[-1] # => 'c'
%w(a b c)[-2] # => 'b'
También puedes combinar índices negativos y positivos.
%w(a b c d e)[1...-1] # => ['b', 'c', 'd']
Otros metodos utiles
Utilice first
para acceder al primer elemento de una matriz:
[1, 2, 3, 4].first # => 1
O first(n)
para acceder a los primeros n
elementos devueltos en una matriz:
[1, 2, 3, 4].first(2) # => [1, 2]
Del mismo modo para el last
y el last(n)
:
[1, 2, 3, 4].last # => 4
[1, 2, 3, 4].last(2) # => [3, 4]
Utilice la sample
para acceder a un elemento aleatorio en una matriz:
[1, 2, 3, 4].sample # => 3
[1, 2, 3, 4].sample # => 1
O sample(n)
:
[1, 2, 3, 4].sample(2) # => [2, 1]
[1, 2, 3, 4].sample(2) # => [3, 4]
Matriz bidimensional
Al usar Array::new
constructor, puede inicializar una matriz con un tamaño dado y una nueva matriz en cada una de sus ranuras. Las matrices internas también pueden tener un tamaño y un valor inicial.
Por ejemplo, para crear una matriz de ceros 3x4:
array = Array.new(3) { Array.new(4) { 0 } }
La matriz generada anteriormente se ve así cuando se imprime con p
:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Puedes leer o escribir en elementos como este:
x = array[0][1]
array[2][3] = 2
Arrays y el operador splat (*)
El operador *
se puede usar para desempaquetar variables y matrices de modo que puedan pasarse como argumentos individuales a un método.
Esto se puede usar para envolver un solo objeto en una matriz si aún no lo está:
def wrap_in_array(value)
[*value]
end
wrap_in_array(1)
#> [1]
wrap_in_array([1, 2, 3])
#> [1, 2, 3]
wrap_in_array(nil)
#> []
En el ejemplo anterior, el método wrap_in_array
acepta un argumento, value
.
Si el value
es una Array
, sus elementos se descomprimen y se crea una nueva matriz que contiene esos elementos.
Si el value
es un solo objeto, se crea una nueva matriz que contiene ese único objeto.
Si el value
es nil
, se devuelve una matriz vacía.
El operador splat es particularmente útil cuando se usa como argumento en métodos en algunos casos. Por ejemplo, permite que los valores y matrices individuales y nil
se manejen de manera consistente:
def list(*values)
values.each do |value|
# do something with value
puts value
end
end
list(100)
#> 100
list([100, 200])
#> 100
#> 200
list(nil)
# nothing is outputted
Descomposición
Cualquier matriz se puede descomponer rápidamente asignando sus elementos a múltiples variables. Un ejemplo simple:
arr = [1, 2, 3]
# ---
a = arr[0]
b = arr[1]
c = arr[2]
# --- or, the same
a, b, c = arr
Al preceder una variable con el operador splat ( *
), se coloca una matriz de todos los elementos que no han sido capturados por otras variables. Si no queda ninguno, se asigna una matriz vacía. Solo se puede usar un splat en una sola tarea:
a, *b = arr # a = 1; b = [2, 3]
a, *b, c = arr # a = 1; b = [2]; c = 3
a, b, c, *d = arr # a = 1; b = 2; c = 3; d = []
a, *b, *c = arr # SyntaxError: unexpected *
La descomposición es segura y nunca plantea errores. nil
s se asignan donde no hay elementos suficientes, que coinciden con el comportamiento del operador []
cuando se accede a un índice fuera de límites:
arr[9000] # => nil
a, b, c, d = arr # a = 1; b = 2; c = 3; d = nil
La descomposición intenta llamar to_ary
implícita en la cesión de los objetos. Al implementar este método en su tipo, obtiene la capacidad de descomponerlo:
class Foo
def to_ary
[1, 2]
end
end
a, b = Foo.new # a = 1; b = 2
Si el objeto que está siendo descompuesto no respond_to?
to_ary
, se trata como una matriz de un solo elemento:
1.respond_to?(:to_ary) # => false
a, b = 1 # a = 1; b = nil
La descomposición también se puede anidar utilizando una expresión de descomposición delimitada por ()
en lugar de lo que de otro modo sería un elemento único:
arr = [1, [2, 3, 4], 5, 6]
a, (b, *c), *d = arr # a = 1; b = 2; c = [3, 4]; d = [5, 6]
# ^^^^^
Esto es efectivamente lo contrario de splat .
En realidad, cualquier expresión de descomposición puede ser delimitada por ()
. Pero para el primer nivel la descomposición es opcional.
a, b = [1, 2]
(a, b) = [1, 2] # the same thing
Caso perimetral: un solo identificador no se puede usar como patrón de desestructuración, ya sea externo o anidado:
(a) = [1] # SyntaxError
a, (b) = [1, [2]] # SyntaxError
Cuando se asigna un literal de matriz a una expresión de desestructuración, se puede omitir []
externo:
a, b = [1, 2]
a, b = 1, 2 # exactly the same
Esto se conoce como asignación paralela , pero utiliza la misma descomposición debajo del capó. Esto es particularmente útil para intercambiar valores de variables sin emplear variables temporales adicionales:
t = a; a = b; b = t # an obvious way
a, b = b, a # an idiomatic way
(a, b) = [b, a] # ...and how it works
Los valores se capturan cuando se construye el lado derecho de la asignación, por lo que usar las mismas variables como origen y destino es relativamente seguro.
Convierta una matriz multidimensional en una matriz unidimensional (aplanada)
[1, 2, [[3, 4], [5]], 6].flatten # => [1, 2, 3, 4, 5, 6]
Si tiene una matriz multidimensional y necesita convertirla en una matriz simple (es decir, unidimensional), puede usar el método #flatten
.
Obtener elementos de matriz únicos
En caso de que necesite leer una matriz evitando las repeticiones , use el método #uniq
:
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq
#=> [1, 2, 3, 4, 5]
En su lugar, si desea eliminar todos los elementos duplicados de una matriz, puede usar #uniq!
método:
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq!
#=> [1, 2, 3, 4, 5]
Mientras que la salida es la misma, #uniq!
También almacena la nueva matriz:
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq
#=> [1, 2, 3, 4, 5]
a
#=> [1, 1, 2, 3, 4, 4, 5]
a = [1, 1, 2, 3, 4, 4, 5]
a.uniq!
#=> [1, 2, 3, 4, 5]
a
#=> [1, 2, 3, 4, 5]
Obtener todas las combinaciones / permutaciones de una matriz
El método de permutation
, cuando se llama con un bloque, produce una matriz bidimensional que consiste en todas las secuencias ordenadas de una colección de números.
Si este método se llama sin un bloque, devolverá un enumerator
. Para convertir a una matriz, llame al método to_a
.
Ejemplo | Resultado |
---|---|
[1,2,3].permutation | #<Enumerator: [1,2,3]:permutation |
[1,2,3].permutation.to_a | [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] |
[1,2,3].permutation(2).to_a | [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]] |
[1,2,3].permutation(4).to_a | [] -> Sin permutaciones de longitud 4 |
El método de combination
, por otro lado, cuando se llama con un bloque produce una matriz bidimensional que consta de todas las secuencias de una colección de números. A diferencia de la permutación, el orden se ignora en las combinaciones. Por ejemplo, [1,2,3]
es lo mismo que [3,2,1]
Ejemplo | Resultado |
---|---|
[1,2,3].combination(1) | #<Enumerator: [1,2,3]:combination |
[1,2,3].combination(1).to_a | [[1],[2],[3]] |
[1,2,3].combination(3).to_a | [[1,2,3]] |
[1,2,3].combination(4).to_a | [] -> Sin combinaciones de longitud 4 |
Llamar al método de combinación por sí mismo resultará en un enumerador. Para obtener una matriz, llame al método to_a
.
Los métodos de repeated_permutation
repeated_combination
y de repeated_permutation
son similares, excepto que el mismo elemento puede repetirse varias veces.
Por ejemplo, las secuencias [1,1]
, [1,3,3,1]
, [3,3,3]
no serían válidas en combinaciones y permutaciones regulares.
Ejemplo | # Combos |
---|---|
[1,2,3].combination(3).to_a.length | 1 |
[1,2,3].repeated_combination(3).to_a.length | 6 |
[1,2,3,4,5].combination(5).to_a.length | 1 |
[1,2,3].repeated_combination(5).to_a.length | 126 |
Crea una matriz de números o letras consecutivas
Esto se puede lograr fácilmente llamando a Enumerable#to_a
en un objeto Range
:
(1..10).to_a #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
(a..b)
significa que incluirá todos los números entre ay b. Para excluir el último número, use a...b
a_range = 1...5
a_range.to_a #=> [1, 2, 3, 4]
o
('a'..'f').to_a #=> ["a", "b", "c", "d", "e", "f"]
('a'...'f').to_a #=> ["a", "b", "c", "d", "e"]
Un atajo conveniente para crear una matriz es [*a..b]
[*1..10] #=> [1,2,3,4,5,6,7,8,9,10]
[*'a'..'f'] #=> ["a", "b", "c", "d", "e", "f"]
Eliminar todos los elementos nil de una matriz con #compact
Si resulta que una matriz tiene uno o más elementos nil
y estos deben eliminarse, ¡ Array#compact
o Array#compact!
Se pueden utilizar métodos, como se muestra a continuación.
array = [ 1, nil, 'hello', nil, '5', 33]
array.compact # => [ 1, 'hello', '5', 33]
#notice that the method returns a new copy of the array with nil removed,
#without affecting the original
array = [ 1, nil, 'hello', nil, '5', 33]
#If you need the original array modified, you can either reassign it
array = array.compact # => [ 1, 'hello', '5', 33]
array = [ 1, 'hello', '5', 33]
#Or you can use the much more elegant 'bang' version of the method
array = [ 1, nil, 'hello', nil, '5', 33]
array.compact # => [ 1, 'hello', '5', 33]
array = [ 1, 'hello', '5', 33]
Finalmente, note que si #compact
o #compact!
se invocan en una matriz sin elementos nil
, estos devolverán nil.
array = [ 'foo', 4, 'life']
array.compact # => nil
array.compact! # => nil
Crear matriz de números
La forma normal de crear una matriz de números:
numbers = [1, 2, 3, 4, 5]
Los objetos de rango pueden usarse ampliamente para crear una matriz de números:
numbers = Array(1..10) # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers = (1..10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#step
métodos #step
y #map
nos permiten imponer condiciones en el rango de números:
odd_numbers = (1..10).step(2).to_a # => [1, 3, 5, 7, 9]
even_numbers = 2.step(10, 2).to_a # => [2, 4, 6, 8, 10]
squared_numbers = (1..10).map { |number| number * number } # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Todos los métodos anteriores cargan los números con impaciencia. Si tienes que cargarlos perezosamente:
number_generator = (1..100).lazy # => #<Enumerator::Lazy: 1..100>
number_generator.first(10) # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Cast to Array desde cualquier objeto
Para obtener Array de cualquier objeto, use Kernel#Array
.
Lo siguiente es un ejemplo:
Array('something') #=> ["something"]
Array([2, 1, 5]) #=> [2, 1, 5]
Array(1) #=> [1]
Array(2..4) #=> [2, 3, 4]
Array([]) #=> []
Array(nil) #=> []
Por ejemplo, podría reemplazar el método join_as_string
del siguiente código
def join_as_string(arg)
if arg.instance_of?(Array)
arg.join(',')
elsif arg.instance_of?(Range)
arg.to_a.join(',')
else
arg.to_s
end
end
join_as_string('something') #=> "something"
join_as_string([2, 1, 5]) #=> "2,1,5"
join_as_string(1) #=> "1"
join_as_string(2..4) #=> "2,3,4"
join_as_string([]) #=> ""
join_as_string(nil) #=> ""
al siguiente código.
def join_as_string(arg)
Array(arg).join(',')
end