2014-09-24 25 views
5

Mam tablicę:Jak mogę przetransponować różne ruby?

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

Mam następujący kod:

arr.transpose 

ale to nie działa, jak go rozwiązać?

jestem coraz

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

moje rozwiązanie:

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

wyjściowy:

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

Jaki jest oczekiwany wynik dla danej tablicy? – falsetru

+0

Zobacz http://stackoverflow.com/questions/21455310/why-does-ruby-have-zip-and-transpose-when-they-do-the-same-thing, aby zrozumieć, dlaczego #transpose nie działa. –

+0

Odpowiedź, chociaż nie mogę zaksięgować jako takiej, jest taka, że ​​liczba elementów musi być taka sama dla tej operacji. –

Odpowiedz

8

Podobną odpowiedź został opublikowany (ale usunięte) godziny wcześniej:

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

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

Powyższe równoważna :

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

To podejście zakłada, że ​​pierwsza podrzędność jest zawsze najdłuższa. W przeciwnym wypadku wynik zostanie obcięty:

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

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

Szukałem bezpiecznej metody transpozycji i użyłem twojego rozwiązania. Wydaje się, że działa tylko wtedy, gdy pierwsza macierz jest większa niż wszystkie pozostałe. Używanie go z 'arr.reverse' zwraca' [[6, 4, 1]] 'zamiast' [[6, 4, 1], [nil, 5, 2], [nil, nil, 3]] '. –

+1

@EricDuminil, zgadza się, zaktualizowałem odpowiedź odpowiednio. – Stefan

0

Jeśli długość subarrays nie pasują, IndexError jest podniesiony.

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

należy:

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

lub

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

W jaki sposób udało ci się odpowiedzieć, gdy pytanie jest zamknięte ... _Różne! _ –

+0

Tak zabawne, jestem też ciekawy. –

+0

Może już zaczęli, czy coś. –

7

Korzystanie zip jak na odpowiedź Stefana jest najbardziej proste, ale jeśli nalegać na użyciu transpose, a następnie:

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

Albo bez użycia albo:

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

To najlepsze rozwiązanie do bezpiecznej transpozycji.Użycie 'zip' działa tylko wtedy, gdy pierwsza tablica jest większa niż pozostałe. –