Reputation: 318
Assume we have a 1-d Matrix, with random length:
M = [102,4,12,6,8,3,4,65,23,43,111,4]
Moreover I have a vector with values that are linked to the index of M:
V = [1,5]
What i want is a simple code of:
counter = 1;
NewM = zeros(length(V)*3,1);
for i = 1:length(V)
NewM(counter:(counter+2)) = M(V(i):(V(i)+2))
counter = counter+3;
end
So, the result will be
NewM = [102,4,12,8,3,4]
In other words, I want the V to V+2 values from M in a new array. I'm pretty sure this can be done easier, but I'm struggeling with how to implement it in arrayfun /bsxfun...
bsxfun(@(x,y) x(y:(y+2)),M,V)
Upvotes: 1
Views: 936
Reputation: 3849
With bsxfun
it's about getting the Vi on one dimension and the +0, +1 +2 on the other:
M = [102,4,12,6,8,3,4,65,23,43,111,4];
V = [1,5];
NewM = M( bsxfun(@plus, V(:), 0:2) )
NewM =
102 4 12
8 3 4
Or if you want a line:
NewM = reshape(NewM.', 1, [])
NewM =
102 4 12 8 3 4
Upvotes: 3
Reputation: 45752
One fully vectorized solution is to expand V
to create the correct indexing vector. In your case:
[1,2,3,5,6,7]
You can expand V
to replicate each of it's elements n
times and then add a repeating vector of 0:(n-1)
:
n = 3;
idx = kron(V, ones(1,n)) + mod(0:numel(V)*n-1,n)
So here kron(V, ones(1,n))
will return [1,1,1,5,5,5]
and mod(0:numel(V)*n-1,n)
will return [0,1,2,0,1,2]
which add up to the required indexing vector [1,2,3,5,6,7]
and now it's just
M(idx)
Note a slightly faster alternative to kron
is reshape(repmat(V,n,1),1,[])
Upvotes: 1
Reputation: 73206
Using arrayfun
(note that M
is used as an "external" matrix entity in this scope, whereas the arrayfun
anonymous function parameter x
correspond to the elements in V
)
NewM = cell2mat(arrayfun(@(x) M(x:x+2), V, 'UniformOutput', false));
With result
NewM =
102 4 12 8 3 4
Upvotes: 2