Mam tablicę tablic, coś w rodzaju:
[
[1,2,3],
[1,2,3],
[1,2,3],
]
Chciałbym to przetransponować, aby uzyskać następującą tablicę:
[
[1,1,1],
[2,2,2],
[3,3,3],
]
Programowo nie jest to trudne przy użyciu pętli:
function transposeArray(array, arrayLength){
var newArray = [];
for(var i = 0; i < array.length; i++){
newArray.push([]);
};
for(var i = 0; i < array.length; i++){
for(var j = 0; j < arrayLength; j++){
newArray[j].push(array[i][j]);
};
};
return newArray;
}
Wydaje się to jednak nieporęczne i czuję, że powinien istnieć łatwiejszy sposób na zrobienie tego. Jest tu?
javascript
arrays
matrix
transpose
ckersch
źródło
źródło
arrayLength
dokładnie służy parametr? Aby upewnić się, że nie wykraczasz poza określoną liczbę elementów w tablicy?Odpowiedzi:
źródło
array[0].map
zamiastarray.map
?array[0].map
ponieważ chce iterować dowolną liczbę razy, że istnieją kolumny,array.map
sprawdziłby liczbę wierszy.loops
są 45% wolniejsze niżmap
. I tak, transponuje poprawnie, więc drugi bieg zwraca początkową macierz.oto moja implementacja w nowoczesnej przeglądarce (bez zależności):
źródło
Możesz użyć underscore.js.
źródło
rambda
możesz to zrobićconst transpose = apply(zip)
najkrótsza droga z
lodash
/underscore
ies6
:gdzie
matrix
może być:źródło
_.zip.apply(_, matrix)
Wiele dobrych odpowiedzi! Skonsolidowałem je w jedną odpowiedź i zaktualizowałem część kodu, aby uzyskać bardziej nowoczesną składnię:
One- liners inspirowane przez Fawad Ghafoor i Óscar Gómez Alcañiz
Funkcjonalny styl podejścia z redukcją autorstwa Andrew Tatomyr
Lodash / Underscore użytkownika marcel
Podejście waniliowe
Podejście Vanilla in-place ES6 inspirowane przez Emanuela Saringana
źródło
Schludny i czysty:
Poprzednie rozwiązania mogą prowadzić do niepowodzenia w przypadku podania pustej tablicy.
Tutaj jest to funkcja:
Aktualizacja. Jeszcze lepiej można to napisać za pomocą operatora spreadu:
źródło
Możesz to zrobić na miejscu, wykonując tylko jeden przejazd:
źródło
[arr[j][j],arr[i][j]] = [arr[i][j],arr[j][j]]
ale to nie działa, czy coś mi brakuje?[arr[j][i], arr[i][j]] = [arr[i][j], arr[j][i]]
. Zwróć uwagę, że masz pewnearr[j][j]
terminy, które zawsze będą odnosić się do komórek na przekątnej.Po prostu kolejna odmiana użycia
Array.map
. Korzystanie z indeksów pozwala na transpozycję macierzy, w którychM != N
:Wszystko, co trzeba zrobić, to odwzorowanie elementów najpierw w kolumnie, a następnie w wierszu.
źródło
Jeśli masz możliwość korzystania ze składni Ramda JS i ES6, możesz to zrobić w inny sposób:
źródło
transpose
-function teraz.Inne podejście polegające na iteracji tablicy od zewnątrz do wewnątrz i zredukowaniu macierzy poprzez mapowanie wartości wewnętrznych.
źródło
Jeśli użycie RamdaJS jest opcją, można to osiągnąć w jednej linii:
R.transpose(myArray)
źródło
Możesz to osiągnąć bez pętli, korzystając z następującego.
Array
Array.prototype.map
Array.prototype.reduce
Array.prototype.join
String.prototype.split
Wygląda bardzo elegancko i nie wymaga żadnych zależności, takich jak jQuery lub Underscore.js .
Zminimalizowane
Oto demo, które wrzuciłem razem. Zwróć uwagę na brak pętli :-)
źródło
ES6 1linery jako:
tak samo jak Óscar, ale jak wolisz obrócić go w prawo:
źródło
Edycja: ta odpowiedź nie transponuje macierzy, ale ją obróci. Przede wszystkim nie przeczytałem uważnie pytania: D
obrót w prawo i w lewo:
źródło
Powyższe odpowiedzi okazały się trudne do odczytania lub zbyt szczegółowe, więc sam je piszę. Myślę, że jest to najbardziej intuicyjny sposób implementacji transpozycji w algebrze liniowej, nie wykonujesz wymiany wartości , ale po prostu wstaw każdy element we właściwe miejsce w nowej macierzy:
źródło
Myślę, że jest to nieco bardziej czytelne. Używa
Array.from
i logika jest identyczna z używaniem zagnieżdżonych pętli:Jeśli masz do czynienia z tablicami o nierównej długości, musisz zamienić na
arr[0].length
coś innego:źródło
źródło
Bezbiblioteczna implementacja w języku TypeScript, która działa dla dowolnego kształtu macierzy, który nie obetnie twoich tablic:
źródło
Jedna linijka, która nie zmienia podanej tablicy.
źródło
źródło
źródło
Nie znalazłem odpowiedzi, która mnie satysfakcjonowała, więc napisałem ją sam, myślę, że jest łatwa do zrozumienia i wdrożenia i nadaje się do wszystkich sytuacji.
źródło
Ponieważ nikt do tej pory nie wspomniał o funkcjonalnym podejściu rekurencyjnym, jest to moje podejście. Adaptacja Haskella
Data.List.transpose
.źródło