Eu tenho uma matriz de matrizes, algo como:
[
[1,2,3],
[1,2,3],
[1,2,3],
]
Gostaria de transpor para obter a seguinte matriz:
[
[1,1,1],
[2,2,2],
[3,3,3],
]
Não é difícil fazer isso programaticamente usando loops:
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;
}
Isso, no entanto, parece volumoso, e eu sinto que deve haver uma maneira mais fácil de fazer isso. Existe?
javascript
arrays
matrix
transpose
ckersch
fonte
fonte
arrayLength
parâmetro usado exatamente? Para garantir que você não ultrapasse um certo número de elementos na matriz?Respostas:
fonte
array[0].map
invés dearray.map
?array[0].map
porque ele deseja iterar quantas vezes houver colunas,array.map
iterará quantas linhas existem.loops
são 45% mais lentos quemap
. E sim, ele transpõe corretamente, portanto a segunda execução retorna a matriz inicial.aqui está a minha implementação no navegador moderno (sem dependência):
fonte
Você poderia usar underscore.js
fonte
rambda
você pode apenas fazerconst transpose = apply(zip)
caminho mais curto com
lodash
/underscore
ees6
:onde
matrix
poderia estar:fonte
_.zip.apply(_, matrix)
Muitas boas respostas aqui! Eu as consolidei em uma resposta e atualizei parte do código para obter uma sintaxe mais moderna:
Alinhadores inspirados em Fawad Ghafoor e Óscar Gómez Alcañiz
Estilo de abordagem funcional com redução por Andrew Tatomyr
Lodash / Sublinhado por marcel
Abordagem de baunilha
Abordagem ES6 no local de baunilha inspirada em Emanuel Saringan
fonte
Puro e puro:
Soluções anteriores podem levar à falha no caso de uma matriz vazia ser fornecida.
Aqui está como uma função:
Atualizar. Pode ser escrito ainda melhor com o operador spread:
fonte
Você pode fazer isso no local executando apenas uma passagem:
fonte
[arr[j][j],arr[i][j]] = [arr[i][j],arr[j][j]]
mas não parece funcionar, estou perdendo alguma coisa?[arr[j][i], arr[i][j]] = [arr[i][j], arr[j][i]]
. Observe que você tem algunsarr[j][j]
termos que sempre se referem às células na diagonal.Apenas outra variação usando
Array.map
. O uso de índices permite transpor matrizes ondeM != N
:Tudo o que há para transpor é mapear os elementos primeiro da coluna e depois por linha.
fonte
Se você tem a opção de usar a sintaxe Ramda JS e ES6, aqui está outra maneira de fazê-lo:
fonte
transpose
função agora.Outra abordagem iterando a matriz de fora para dentro e reduzindo a matriz mapeando valores internos.
fonte
Se o uso do RamdaJS for uma opção, isso poderá ser alcançado em uma linha:
R.transpose(myArray)
fonte
Você pode conseguir isso sem loops usando o seguinte.
Array
Array.prototype.map
Array.prototype.reduce
Array.prototype.join
String.prototype.split
Parece muito elegante e não requer nenhuma dependência, como jQuery do Underscore.js .
Minificado
Aqui está uma demonstração que joguei juntos. Observe a falta de loops :-)
fonte
ES6 1liners como:
igual ao Óscar, mas como você prefere girar no sentido horário:
fonte
Editar: Esta resposta não transpõe a matriz, mas a gira. Eu não li a pergunta cuidadosamente em primeiro lugar: D
rotação no sentido horário e anti-horário:
fonte
Eu achei as respostas acima difíceis de ler ou muito detalhadas, então eu mesmo as escrevo. E eu acho que essa é a maneira mais intuitiva de implementar transposição em álgebra linear, você não faz troca de valor , mas apenas insere cada elemento no lugar certo na nova matriz:
fonte
Eu acho que isso é um pouco mais legível. Ele usa
Array.from
e a lógica é idêntica ao uso de loops aninhados:Se você estiver lidando com matrizes de comprimento desigual, precisará substituir
arr[0].length
por outra coisa:fonte
fonte
fonte
Uma implementação livre de biblioteca no TypeScript que funciona para qualquer formato de matriz que não trunque suas matrizes:
fonte
Uma linha que não altera a matriz fornecida.
fonte
fonte
Não encontrei uma resposta que me satisfizesse, então escrevi uma, acho que é fácil de entender e implementar e adequado para todas as situações.
fonte
Como ninguém até agora mencionou uma abordagem funcional recursiva aqui, é minha opinião. Uma adaptação de Haskell
Data.List.transpose
.fonte