2009-04-27 7 views
8

Tengo una matriz de tamaño n por by que contiene k números por fila. Quiero usar estos k números como índices en una matriz k-dimensional. ¿Existe alguna forma compacta de hacerlo en MATLAB o debo usar un ciclo for?Notación comparativa MATLAB de indexación de matriz

Esto es lo que quiero hacer (en pseudo código MATLAB), pero de una manera más MATLAB-ish:

for row=1:1:n 
    finalTable(row) = kDimensionalMatrix(indexmatrix(row, 1),... 
      indexmatrix(row, 2),...,indexmatrix(row, k)) 
end 

Respuesta

15

Si se quiere evitar tener que utilizar un bucle, esta es probablemente la forma más limpia de hacerlo:

indexCell = num2cell(indexmatrix,1); 
linearIndexMatrix = sub2ind(size(kDimensionalMatrix),indexCell{:}); 
finalTable = kDimensionalMatrix(linearIndexMatrix); 

EXPLICACIÓN:

La primera línea pone cada columna de indexmatrix en celdas separadas de una matriz de celdas usando NUM2CELL. Esto nos permite pasar todos k columnas como un comma-separated list en SUB2IND, una función que convierte índices subindicadas (fila, columna, etc.) en índices lineales (cada elemento de la matriz está numerada de 1 a N, siendo N el número total de elementos en la matriz). La última línea usa estos índices lineales para reemplazar su ciclo for. Se puede encontrar una buena discusión sobre la indexación matricial (subíndice, lineal y lógica) here.

algo más de comida PENSAR ...

La tendencia a alejarse de los bucles en favor de soluciones vectorizados es algo que muchos usuarios de MATLAB (yo incluido) se han acostumbrado a. Sin embargo, las versiones más nuevas de MATLAB manejan el bucle mucho más eficientemente. Como se discutió en this answer a otra pregunta de SO, el uso de bucles for a veces puede dar como resultado un código de ejecución más rápida que el que obtendría con una solución vectorizada.

Ciertamente NO digo que no deba tratar de vectorizar su código nunca más, solo que cada problema es único. Vectorizar será a menudo será más eficiente, pero no siempre. Para su problema, la velocidad de ejecución de los bucles for frente al código vectorizado probablemente dependerá de cuán grandes sean los valores n y k.

6

para tratar los elementos del vector indexmatrix(row, :) como subíndices separados, necesita los elementos como una matriz de celdas. Así, se podría hacer algo como esto

subsCell = num2cell(indexmatrix(row, :)); 
finalTable(row) = kDimensionalMatrix(subsCell{:}); 

Para ampliar subsCell como una lista separada por comas, por desgracia, usted no necesita las dos líneas separadas. Sin embargo, este código es independiente de k.

+0

¡Estupendo! ¿Puedes obtenerlo independientemente del número de filas también? – AnnaR

+0

@AnnaR - Acabo de publicar una respuesta que maneja todas las 'n' filas de' indexmatrix' a la vez. – Shai

0

Convertir sus subíndices en índices lineales de manera hacky

ksz = size(kDimensionalMatrix); 
cksz = cumprod([ 1 ksz(1:end-1)]); 
lidx = (indexmatrix - 1) * cksz' + 1; #' 
% lindx is now (n)x1 linear indices into kDimensionalMatrix, one index per row of indexmatrix 
% access all n values: 
selectedValues = kDimensionalMatrix(lindx); 

Salud!

Cuestiones relacionadas