2012-03-03 20 views
6

Acabo de empezar a aprender ruby. Ahora necesito descubrir la dimensión de una matriz multidimensional. Eché un vistazo a ruby-docs para todos los métodos de matriz, pero no pude encontrar un método que devuelva la dimensión.obteniendo la dimensión de una matriz multidimensional en ruby ​​

Aquí se muestra un ejemplo:

Para [[1, 2],[3,4],[5,6]] la dimensión debe ser 2.

Para [[[1,2],[2,3]],[[3,4],[5]]], la dimensión debe ser 3.

Respuesta

2

No hay una función incorporada para eso, ya que puede haber una definición múltiple de lo que quiere decir con "dimensión" para una matriz. Las matrices de Ruby pueden contener cualquier cosa, incluidos hashes u otras matrices. Es por eso que creo que necesita implementar su propia función para eso.

Asumiendo que por la dimensión que quiere decir "el nivel de anidado más profundo de arrays" esto debe hacer el truco:

def get_dimension a 
    return 0 if a.class != Array 
    result = 1 
    a.each do |sub_a| 
    if sub_a.class == Array 
     dim = get_dimension(sub_a) 
     result = dim + 1 if dim + 1 > result 
    end 
    end 
    return result 
end 

EDIT: y como rubí es un gran lenguaje y le permite hacer algunas cosas de lujo que pueda también hacer get_dimension un método de matriz:

class Array 
    def get_dimension 
    ... # code from above slightly modified 
    end 
end 
+0

si sub_a.class == Array – Short

1

en el caso más simple

depth = Proc.new do |array| 
    depth = 1 
    while Array === array.first do 
    array = array.first 
    depth += 1 
    end 
    depth 
end 

array = [[[1,2],[2,3]],[[3,4],[5]]]  
depth.call(array) 
#=> 3 

O este pequeño método recursivo

def depth(array, depth=1) 
    array = array.send(:first) 
    Array === array ? depth(array, depth+1) : depth 
end 

array = [[[1,2],[2,3]],[[3,4],[5]]]  
depth(array) 
#=> 3 
+0

Por qué proc, no es regular ¿función? –

+0

No estoy seguro, doc%) Es algo conducido por el comportamiento. Estaba en la consola y normalmente uso procs en la consola. Por supuesto, podría reescribirse como un método habitual – fl00r

+0

Solo tengo curiosidad, eso es todo :) –

0

¿Qué tal:

class Object 
    def dimension 
     self.class == Array ? 1 + self[0].dimension : 0 
    end 
end 
[[[1,2],[2,3]],[[3,4],[5]]].dimension 
#=> 3 
+1

otra vez esto no funcionará en el caso a = [3, [1,2]]. La salida será 1 en lugar de 2. Sin embargo, una ligera modificación hará que funcione para ese caso. –

+0

@izomorphius - Me parece que 1 es el valor correcto en ese caso. Tienes razón en que la pregunta no lo deja claro sin embargo. – pguardiario

6

S implementar, solución orientada a objetos.

class Array 
    def depth 
    map {|element| element.depth + 1 }.max 
    end 
end 

class Object 
    def depth 
    0 
    end 
end 
0

Como una modificación del enfoque de Tass:

class Array 
    def depth 
     map{ |element| element.is_a?(Vector) ? element.depth + 1 : 1 }.max 
    end 
end 

Mantiene depth como método de Array, y no requiere la adición de un método para Object.

Por supuesto, eso podría ser lo que quiera si se va a llamar my_object.depth, en el que no sabe de antemano que my_object.class == Array

0

que no estaba satisfecho con las otras soluciones así que escribí una sola línea de hecho, me gustaría utilizar:

def depth(array) 
    array.to_a == array.flatten(1) ? 1 : depth(array.flatten(1)) + 1 
end 

será aplanar la dimensión de matriz 1 en el momento hasta que no pueda aplanar más, mientras cuenta las dimensiones.

¿Por qué es esto mejor?

  • no requiere modificación de clases nativas (evite que si es posible)
  • no utiliza metaprogramming (is_a?, send, respond_to?, etc.)
  • bastante fácil de leer
  • trabajos con los hashes así (nótese array.to_a)
  • realmente funciona (a diferencia de solamente el control de la primera rama, y ​​otras cosas tontas)
Cuestiones relacionadas