2014-09-24 16 views
5

Ho un array:Come posso trasporre matrici di rubini di dimensioni diverse?

arr=[[1,2,3],[4,5],[6]], 

Ho il seguente codice:

arr.transpose 

ma non funziona, come risolverlo?

sto ottenendo

[[1,2,3],[4,5],[6]].transpose 
IndexError: element size differs (2 should be 3) 
    from (irb):13:in `transpose' 
    from (irb):13 
    from /home/durrant 

la mia soluzione:

arr.reduce(&:zip).map(&:flatten) 

uscita:

[[1, 4, 6], [2, 5, nil], [3, nil, nil]] 
+5

Qual è il risultato previsto per l'array specificato? – falsetru

+0

Guardate questo http://stackoverflow.com/questions/21455310/why-does-ruby-have-zip-and-transpose-when-the-the-same-thing per capire perché #transpose non ha funzionato. –

+0

La risposta, anche se non posso pubblicare come tale è che il numero di elementi deve essere lo stesso per questa operazione. –

risposta

8

Una risposta simile è stata pubblicata (tranne quelli eliminati) un'ora prima:

arr = [[1, 2, 3], [4, 5], [6]] 

arr[0].zip(*arr[1..-1]) 
#=> [[1, 4, 6], [2, 5, nil], [3, nil, nil]] 

Quanto sopra è equivalente a :

[1, 2, 3].zip([4, 5], [6]) 

Questo approccio presuppone che il primo sotto-array sia sempre il più lungo. In caso contrario, il risultato verrà troncato:

arr = [[1, 2], [3, 4, 5], [6]] 

arr[0].zip(*arr[1..-1]) 
#=> [[1, 3, 6], [2, 4, nil]] missing: [nil, 5, nil] 
+1

Stavo cercando un metodo di trasposizione sicuro e ho usato la soluzione. Sembra funzionare solo quando il primo array è più grande di tutti gli altri. Usandolo con 'arr.reverse' ritorna' [[6, 4, 1]] 'invece di' [[6, 4, 1], [nil, 5, 2], [nil, nil, 3]] '. –

+1

@EricDuminil è corretto, ho aggiornato la risposta di conseguenza. – Stefan

0

Se la lunghezza dei sottoarray non corrispondono, un IndexError è sollevata.

irb(main):002:0> arr=[[1,2,3],[4,5],[6]] 
=> [[1, 2, 3], [4, 5], [6]] 
irb(main):003:0> arr.transpose 
IndexError: element size differs (2 should be 3) 
    from (irb):3:in `transpose' 
    from (irb):3 
    from /Users/liuxingqi/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>' 

dovrebbe essere:

irb(main):004:0> arr=[[1,2,3],[4,5,6]] 
=> [[1, 2, 3], [4, 5, 6]] 
irb(main):005:0> arr.transpose 
=> [[1, 4], [2, 5], [3, 6]] 

o

irb(main):006:0> arr=[[1,2],[3,4],[5,6]] 
=> [[1, 2], [3, 4], [5, 6]] 
irb(main):007:0> arr.transpose 
=> [[1, 3, 5], [2, 4, 6]] 
+0

Come sei riuscito a _answer_ mentre la domanda è chiusa ... _Strange !! _ –

+0

Sì, divertente, anche io sono curioso. –

+0

Forse avevano già iniziato o qualcosa del genere. –

7

Utilizzando zip come nella risposta di Stefan è la più semplice, ma se ti ostini a usare transpose, quindi:

l = arr.map(&:length).max 
arr.map{|e| e.values_at(0...l)}.transpose 
# => [[1, 4, 6], [2, 5, nil], [3, nil, nil]] 

O senza utilizzando:

Array.new(arr.map(&:length).max){|i| arr.map{|e| e[i]}} 
# => [[1, 4, 6], [2, 5, nil], [3, nil, nil]] 
+3

Questa è la soluzione migliore per una trasposizione sicura.L'uso di 'zip' funziona solo quando il primo array è più grande degli altri. –