MATLAB: проверить, меньше ли следующие n записей вектора определенное значение - PullRequest
0 голосов
/ 05 ноября 2019

Я работаю с большим вектором, который содержит значения линейной комбинации нескольких синусоидальных функций (где первая запись - в 0 миллисекунд, а n - в n миллисекундах). Теперь я хочу извлечь фрагменты вектора, которые содержат (ту же комбинацию) синусоидальные функции, и сохранить их отдельно.

Следовательно, я хочу проверить, равны ли 5 ​​записей рядом друг с другом нулю, что означает этобудет «разрез» между двумя отдельными линейными комбинациями. Если рядом друг с другом есть 5 или более записей, равных нулю, то это то место, где следует сделать разрез. В качестве примера приведем следующий (короткий) вектор.

Позвольте vector = [ 0 0 0 0 0 0 0 8 9 1 0 0 3 2 0 0 0 0 0 6 6 2 0 0 0 1 ], который должен быть разделен на два отдельных вектора, а именно vec1= [8 9 1 0 0 3 2] и vec2= [6 6 2 0 0 0 1].

Я думаю, я мог бы использоватьвстроенная функция find, но я не думаю, что она может искать «по крайней мере» 5 записей рядом друг с другом, которые равны 0, правильно?

Ответы [ 2 ]

2 голосов
/ 05 ноября 2019

Начиная с вашего примера ...

v = [ 0 0 0 0 0 0 0 8 9 1 0 0 3 2 0 0 0 0 0 6 6 2 0 0 0 1 ];

Мы могли бы сделать следующее:

% 1. Create an index `idx` which groups elements either as zeros or non-zeros, 
%    with an increasing group number for each subsequent set
idx = cumsum( [1, diff(v==0) ~= 0] );
% = [ 1 1 1 1 1 1 1 2 2 2 3 3 4 4 5 5 5 5 5 6 6 6 7 7 7 8 ];

% 2. Split by this group, regardless of what's in it
grps = splitapply( @(x){x}, v, idx );
% = { {1×7 double}, {1×3 double}, {1×2 double}, {1×2 double}, {1×5 double}, ... }

% 3. Get the indices for groups, incremented when the 5-zeros condition is met
zIdx = cellfun( @(x) x(1) == 0, grps ); % Just alternating 0/1, as groups alternate
idx = cellfun( @numel, grps ) >= 5 & zIdx;
idx = cumsum( idx ) .* ~idx;
% = [ 0 1 1 1 0 2 2 2 ]

% 4. Group everything together
out = arrayfun( @(x) [grps{idx==x}], 1:max(idx), 'uni', 0 );
% { [8 9 1 0 0 3 2], [6 6 2 0 0 0 1] }

Я не уверен, что это быстрее, чем просто написать цикл .. .

1 голос
/ 05 ноября 2019

Вы можете использовать regexp с опцией split:

v   = [0 0 0 0 0 0 0 8 90 0 0 0 0 1 0 0 3 2 0 0 0 0 0 6 6 2 0 0 0 1 ];
%     vector to string then extract the subvector
r   = regexp(num2str(v),'(?<![0-9])(0\s+){5,}','split')
%     string to vector
out = cellfun(@str2num,r,'UniformOutput',0)

С этим регулярным выражением: (?<![1-9])(0\s+){5,}

(?<![0-9]): проверить, что нулю не предшествуетна цифру, поэтому 90 0 0 0 0 не должен разбивать вектор.

(0\s+){5,}: проверить, по крайней мере, 5 последовательных 0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...