2012-03-03 20 views
6

Ho appena iniziato a imparare il rubino. Ora ho bisogno di capire la dimensione di un array multidimensionale. Ho dato un'occhiata a ruby-docs per tutti i metodi dell'array, ma non sono riuscito a trovare un metodo che restituisse la dimensione.ottenere dimensione della matrice multidimensionale in rubino

Ecco un esempio:

Per [[1, 2],[3,4],[5,6]] la dimensione dovrebbe essere 2.

Per [[[1,2],[2,3]],[[3,4],[5]]], la dimensione dovrebbe essere 3.

risposta

2

Non esiste una funzione incorporata per questo in quanto potrebbero esserci più definizioni riguardo a cosa si intende per "dimensione" per un array. Gli array di Ruby possono contenere qualsiasi cosa, inclusi hash o altri array. Ecco perché credo che sia necessario implementare la propria funzione per questo.

Asuming che per dimensione si intende "il più profondo livello nidificato di array", questo dovrebbe fare il trucco:

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: e come rubino è un grande linguaggio e permette di fare alcune cose di fantasia si può anche fare get_dimension un metodo di Array:

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

if sub_a.class == Array – Short

1

nel caso più semplice

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 

Or questo piccolo metodo ricorsivo

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

Perché proc, non è regolare funzione? –

+0

Non sono sicuro, doc%) Sono cose guidate dal comportamento. Ero nella console e di solito uso procs in console. Naturalmente potrebbe essere riscritto come un metodo normale – fl00r

+0

Sono curioso, tutto qui :) –

0

ne dite:

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

ancora una volta questo non funzionerà nel caso a = [3, [1,2]]. L'output sarà 1 anziché 2. Una leggera modifica lo farà funzionare per quel caso, però. –

+0

@izomorphius - Mi sembra che 1 sia il giusto valore in questo caso. Hai ragione che la domanda non chiarisce però. – pguardiario

6

S imple, soluzione orientata agli oggetti.

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

class Object 
    def depth 
    0 
    end 
end 
0

Come modifica dell'approccio di Tass:

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

Mantiene depth come metodo di Array, e non richiede l'aggiunta di un metodo per Object.

Naturalmente, che potrebbe essere quello che vuoi, se avete intenzione di chiamare my_object.depth, in cui non si sa in anticipo che my_object.class == Array

0

non ero soddisfatto con le altre soluzioni così ho scritto una battuta avrei realtà uso:

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

sarà appiattire la dimensione dell'array 1 al momento fino a che non può appiattire più, contando le dimensioni.

Perché è meglio?

  • non richiede la modifica di classi native (evitare che se possibile)
  • non usa metaprogrammazione (is_a?, send, respond_to?, etc.)
  • abbastanza facile da leggere
  • opere con hash così (notare array.to_a)
  • effettivamente funziona (a differenza di solo il controllo del primo ramo, e altre cose stupide)
Problemi correlati