2014-10-07 1 views
1

Я пытаюсь взять вектор и разделить на разделы. код требует от меня создания отдельного вектора, когда возрастающий порядок останавливается следующим образом: [3, 5, 9, 21, 27, 15, 10, 13] будет разделен на три блока [3 5 9 21 27], [15] и [10, 13].Разделить массив на блоки, где каждый блок является самой длинной восходящей (увеличивающейся) последовательностью

Я не должен использовать петлю, поэтому было бы полезно, если кто-то сможет мне помочь. Благодарю.

+0

Добро пожаловать в stackoverflow! Пожалуйста, подумайте о том, чтобы принять ответ (тот, который наилучшим образом ответил на ваш вопрос), чтобы указать систему, что ваша проблема решена (зеленая галочка слева). – thewaywewalk

ответ

0

Функция diff вычисляет разницу между смежными элементами массива. Элемент, который является отрицательным в результате diff, указывает на то место, где восходящий порядок «сломан».

Итак:

v = [3, 5, 9, 21, 27, 15, 10, 13]; 
dv = diff(v); 
nb = sum(dv <= 0); % number of blocks 
b = cell(1, nb); % container of blocks 

ix = find(dv <= 0); % start indices of blocks 
ix0 = 1; 
for k = 1:nb 
     ix1 = ix(k); 
     b{k} = a(ix0:ix1); 
     ix0 = ix1 +1 ; 
end; 

Мое мнение таково, что трудно избежать с помощью петель, однако, приведенный выше код является гораздо более «мягким» относительно вычислительной нагрузки по сравнению с грубым силовым методом нахождения блоков элемента по элементу. не

2

Нет петли, одна линия, я надеюсь, что все в порядке;)

a = [3, 5, 9, 21, 27, 15, 10, 13]; 

output = accumarray(cumsum([0; diff(a(:))] < 0)+1, a, [], @(x) {x}) 

некоторые пояснения:

%// find out where the vector decreases: 
da = [0; diff(a(:))] 
%// and create a mask 
mask = da < 0 
%// sum the mask up cumulatively and add +1 
subs = cumsum(mask) + 1 
%// use accumarray to gather everything 
output = accumarray(subs,a,[],@(x) {x}) 

Если есть последующее такое же количество, как и здесь:

a = [3, 5, 9, 21, 27, 27, 15, 10, 13]; 

решение выше считает seco й 27 к первой группе, если вы хотите быть отдельная группа, изменить маску:

mask = da <= 0 
+0

+1 для приятного решения. –

+1

+1 от меня тоже. Я всегда поддерживаю решение 'tankarray' – rayryeng

+0

Отличное решение! –

1

Это можно сделать очень легко с mat2cell:

x = find(diff(a)<0); 
result = mat2cell(a, 1, [x(1) diff(x) numel(a)-x(end)]); 

Если вы хотите один -liner:

result = mat2cell(a, 1, diff(find(diff([inf a -inf])<0))); 
+0

То же самое происходит, когда я запускаю это тоже, я получаю [4x1 double] [15] [2x1 double] – electricsurge31

+0

+1! и комментарии позволяют мне немного хихикать. – thewaywewalk

Смежные вопросы