Vectorizando la noción de Colón (:) – valores entre dos vectores en MATLAB

Tengo dos vectores, idx1 e idx2 , y quiero obtener los valores entre ellos. Si idx1 e idx2 fueran números y no vectores, podría hacerlo de la siguiente manera:

 idx1=1; idx2=5; values=idx1:idx2 % Result % values = % % 1 2 3 4 5 

Pero en mi caso, idx1 e idx2 son vectores de longitud variable. Por ejemplo, para length = 2:

 idx1=[5,9]; idx2=[9 11]; 

¿Puedo usar el operador de dos puntos para obtener directamente los valores intermedios? Esto es, algo similar a lo siguiente:

 values = [5 6 7 8 9 9 10 11] 

Sé que puedo hacer idx1(1):idx2(1) e idx1(2):idx2(2) , esto es, extraer los valores de cada columna por separado, así que si no hay otra solución, puedo hacerlo con un for-loop, pero tal vez Matlab puede hacer esto más fácilmente.

Su resultado de muestra no es legal. Una matriz no puede tener filas de diferente longitud. Lo que puedes hacer es crear una matriz de celdas usando arrayfun :

 values = arrayfun(@colon, idx1, idx2, 'Uniform', false) 

Para convertir la matriz de células resultante en un vector, puede usar cell2mat :

 values = cell2mat(values); 

Alternativamente, si todos los vectores en la matriz de células resultante tienen la misma longitud, puede construir una matriz de salida de la siguiente manera:

 values = vertcat(values{:}); 

Intente tomar la unión de los conjuntos. Dado los valores de idx1 e idx2 que suministró, ejecute

 values = union(idx1(1):idx1(2), idx2(1):idx2(2)); 

Que producirá un vector con los valores [5 6 7 8 9 10 11] , según lo deseado.

No pude lograr que funcione la solución de @Eitan, aparentemente necesita especificar parámetros para dos puntos. La pequeña modificación que sigue lo hizo funcionar en mi versión R2010b:

 step = 1; idx1 = [5, 9]; idx2 = [9, 11]; values = arrayfun(@(x,y)colon(x, step, y), idx1, idx2, 'UniformOutput', false); values=vertcat(cell2mat(values)); 

Tenga en cuenta que step = 1 es en realidad el valor predeterminado en colon , y Uniform se puede usar en lugar de UniformOutput , pero los he incluido para completar.

Hay una gran publicación de Loren en el blog titulada Vectorizing the Noion of Colon (:) . Incluye una respuesta que es aproximadamente 5 veces más rápida (para arreglos grandes) que usar arrayfun o a for -loop y es similar a la deencoding de longitud de ejecución:

La idea es expandir las secuencias de colon. Sé las longitudes de cada secuencia, así que sé los puntos de partida en la matriz de salida. Rellene los valores después de los valores de inicio con 1s. Luego descubro cuánto saltar del final de una secuencia al comienzo de la siguiente. Si hay valores de inicio repetidos, los saltos pueden ser negativos. Una vez que se completa esta matriz, la salida es simplemente la sum acumulativa o cumsum de la secuencia.

 function x = coloncatrld(start, stop) % COLONCAT Concatenate colon expressions % X = COLONCAT(START,STOP) returns a vector containing the values % [START(1):STOP(1) START(2):STOP(2) START(END):STOP(END)]. % Based on Peter Acklam's code for run length decoding. len = stop - start + 1; % keep only sequences whose length is positive pos = len > 0; start = start(pos); stop = stop(pos); len = len(pos); if isempty(len) x = []; return; end % expand out the colon expressions endlocs = cumsum(len); incr = ones(1, endlocs(end)); jumps = start(2:end) - stop(1:end-1); incr(endlocs(1:end-1)+1) = jumps; incr(1) = start(1); x = cumsum(incr); 
Intereting Posts