Векторизация понятия толстой кишки (:) - значения между двумя векторами в MATLAB - программирование
Подтвердить что ты не робот

Векторизация понятия толстой кишки (:) - значения между двумя векторами в MATLAB

У меня есть два вектора idx1 и idx2, и я хочу получить значения между ними. Если idx1 и idx2 были числами, а не векторами, я мог бы сделать это следующим образом:

idx1=1;
idx2=5;
values=idx1:idx2 

% Result
 % values =
 % 
 %    1     2     3     4     5

Но в моем случае idx1 и idx2 являются векторами переменной длины. Например, для длины = 2:

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

Можно ли использовать оператор двоеточия для непосредственного получения значений между ними? Это похоже на следующее:

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

Я знаю, что могу делать idx1(1):idx2(1) и idx1(2):idx2(2), это извлекать значения для каждого столбца отдельно, поэтому, если другого решения нет, я могу сделать это с помощью цикла for, но, возможно, Matlab может сделать это легче.

4b9b3361

Ответ 1

Ваш образец не является законным. Матрица не может иметь строки разной длины. Вы можете создать массив ячеек с помощью arrayfun:

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

Чтобы преобразовать результирующий массив ячеек в вектор, вы можете использовать cell2mat:

values = cell2mat(values);

В качестве альтернативы, если все векторы в результирующем массиве ячеек имеют одинаковую длину, вы можете построить выходную матрицу следующим образом:

values = vertcat(values{:});

Ответ 2

Попробуйте взять объединение множеств. Учитывая значения idx1 и idx2, которые вы предоставили, запустите

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

Который даст желаемый вектор со значениями [5 6 7 8 9 10 11].

Ответ 3

Я не мог получить решение @Eitan для работы, видимо, вам нужно указать параметры для двоеточия. Последующая небольшая модификация заработала мою версию 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));

Обратите внимание, что step = 1 фактически является значением по умолчанию в colon, а Uniform может использоваться вместо UniformOutput, но я включил их для полноты.

Ответ 4

У Лорена есть замечательная запись в блоге Векторизация понятия "Колон" (:). Он включает в себя ответ, который примерно в 5 раз быстрее (для больших массивов), чем при использовании arrayfun или for -loop и похож на декодирование длины строки:

Идея состоит в том, чтобы расширить последовательности двоеточия. Я знаю, сколько каждая последовательность, поэтому я знаю начальные точки в выходном массиве. заполнить значения после начальных значений с 1s. Затем я выясню, сколько для перехода от конца одной последовательности к началу следующей. Если повторяются начальные значения, скачки могут быть отрицательными. однажды этот массив заполняется, выход представляет собой просто суммарную сумму или cumsum последовательности.

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 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);