Векторизация понятия толстой кишки (:) - значения между двумя векторами в 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 может сделать это легче.
Ответы
Ответ 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);