2012-02-25 5 views
1

Мне интересно, могу ли я сделать следующее в Matlab. Написание наивного цикла для проблемы довольно просто, но я пытаюсь найти, есть ли какие-либо специализированные функции, которые можно использовать (возможно, arrayfun/accumarray (?) - оба из которых у меня большие проблемы с пониманием!) Спасибо заранее ,Как разделить вектор со ссылкой на другой вектор в Matlab?

Скажем, у меня есть два вектора следующим образом (в Matlab):

A = [15 4 9 6 7 5 11 3 14]; 
B = [2 7 13]; 

Я хотел бы сделать следующее:

  1. Сортировать B, если не сортируется уже.
  2. Для каждого последующего окна в B (т. Е. [2,7], [7,13]) найдите соответствующие элементы в A, которые находятся внутри окна.
  3. В этом «секционированном» A декремент на 1 n раз из этих элементов в A, которые лежат в n-ом окне B.

Пример: В приведенном выше случае первое окно B - [2,7]. Элементы в A, которые лежат в этом окне, - [5,4,3,6]. Поскольку они лежат в первом окне B, мне нужно уменьшить 1, один раз от каждого из этих элементов. Новый A будет выглядеть следующим образом после этой операции: A = [15 3 9 5 7 4 11 2 14];

Может ли эта проблема быть уменьшена до нескольких вызовов функций в Matlab или один должен пройти через наивную бизнес петли в любом случае? Благодаря!

+0

Я узнал, что в последних версиях matlab для петель больше не узкое место. (см. http://stackoverflow.com/questions/9217024/selecting-a-vector-from-a-matrix-without-using-sub2ind/9217123#comment11612988_9217123). Вероятно, вы не получите многого путем векторизации. но если вы публикуете свой существующий код, мы можем проверить, возможна ли оптимизация. – bdecaf

+0

О, ладно! Хорошо знать. Спасибо за ссылку. – mskb

+0

@bdecaf: TheMathWorks упорно работали, чтобы ускорить петлю, так как R2007. Для простых циклов оптимизация довольно хороша, но как только цикл становится более сложным, вы будете страдать от накладных расходов Matlab с каждым вызовом функции. Таким образом, векторизация может по-прежнему приносить улучшения, если у вас достаточно доступной памяти. – Jonas

ответ

2

Это можно сделать довольно легко, используя функцию histc, чтобы определить, в каком бункере (то, что вы назвали «окном»).

A = [15 4 9 6 7 5 11 3 14]; 
B = [2 7 13]; 
B = sort(B); 
[~, bin] = histc(A, B); 
A = A - bin; 

редактировать: Я заметил, что мое решение отличается от вашего, но я подозреваю, что вы сделали ошибку в вашем расчете. Вам нужно вычесть 2 из значений во втором ящике или оставить их как есть? Если вы хотите изменить значения только в первом ящике, последняя строка должна читать A(bin==1) = A(bin==1) - 1.

A = [15 4 9 6 7 5 11 3 14]; % initial value of A 
A = [15 3 9 5 7 4 11 2 14]; % your reference result 
A = [15 3 7 5 5 4 9 2 14]; % my result (as above) 
A = [15 3 9 5 7 4 11 2 14]; % my result with A(bin==1) = A(bin==1) - 1 

Чтобы изменить в том, что бен значение на краю бункера должен в конечном итоге, вы можете попробовать добавить/вычесть eps из B.

+0

+1 - Эгон удары снова :) –

+0

Спасибо @Egon. Ваше решение было замечательным. Мне нужно вычесть 2 из второго бина, n из n-го бина. – mskb

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