2014-09-24 12 views
5

Ich habe ein Array:Wie kann ich Ruby Arrays unterschiedlicher Größe transponieren?

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

ich den folgenden Code haben:

arr.transpose 

aber es funktioniert nicht, wie es zu lösen?

Ich erhalte

[[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 

meine Lösung:

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

Ausgang:

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

Was ist das erwartete Ergebnis für das gegebene Array? – falsetru

+0

Schauen Sie http://stackoverflow.com/questions/21455310/why-does-ruby-have-zip-and-transpose-when-they-do-the-some-thing um zu verstehen, warum #transpose nicht funktioniert hat. –

+0

Die Antwort, obwohl ich nicht so schreiben kann, ist, dass die Anzahl der Elemente für diese Operation gleich sein muss. –

Antwort

8

Eine ähnliche Antwort wurde veröffentlicht (aber gelöscht) eine Stunde früher:

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

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

Die oben entspricht :

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

Bei diesem Ansatz wird davon ausgegangen, dass Ihr erstes Unterfeld immer das längste ist. Andernfalls wird das Ergebnis abgeschnitten:

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

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

Ich war auf der Suche nach einer sicheren Transponierungsmethode und nutzte Ihre Lösung. Es scheint nur zu funktionieren, wenn das erste Array größer als alle anderen ist. Wenn Sie es mit 'arr.reverse 'verwenden, wird' [[6, 4, 1]]' 'anstelle von' [[6, 4, 1], [nil, 5, 2], [nil, nil, 3]] 'zurückgegeben. –

+1

@EricDuminil das ist richtig, ich habe die Antwort entsprechend aktualisiert. – Stefan

0

Wenn die Länge des Sub-Arrays nicht übereinstimmen, ein Indexerror angehoben.

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>' 

sollte sein:

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]] 

oder

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

Wie hast du es geschafft _answer_ während Frage geschlossen ist ... _Strange !! _ –

+0

Ja lustig, ich bin auch neugierig. –

+0

Vielleicht hatten sie schon angefangen oder so. –

7

Mit zip wie in Stefan Antwort ist die einfachste, aber wenn Sie darauf bestehen, transpose verwenden, dann:

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

oder ohne Verwendung von entweder:

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

Dies ist die beste Lösung für eine sichere Übertragung.Die Verwendung von 'zip' funktioniert nur, wenn das erste Array größer als die anderen ist. –

Verwandte Themen