Reputation: 241
I have a vector, let it be b=[1 2 2 3 4 1 2 1 4...]
and another vector A(n)
which I want to divide in vectors in the following way:
A(1)
and A(6)
and A(8)
will all belong in vector 1 called Av1
A(2)
and A(6)
and A(8)
will all belong in vector 2 called Av2
etc...
The vector b could have numbers from 1:n meaning I can't write code individually for each Av. Basically each b(i) corresponds to each A(i) and tells me which subvector it will belong to. Anyone has any idea?
Thank you in advance!
Upvotes: 0
Views: 293
Reputation: 112769
As @rayryeng says, don't create separate variables; use a cell array instead. You can do that with accumarray
as follows:
First define your data:
b = [ 1 2 2 3 4 1 2 1 4 ];
A = 1:numel(b); %// for example
Then
C = accumarray(b(:), A(:), [], @(x) {x});
gives
>> C
C =
[3x1 double]
[3x1 double]
[ 4]
[2x1 double]
>> celldisp(C)
C{1} =
6
8
1
C{2} =
7
3
2
C{3} =
4
C{4} =
5
9
If you want to keep the original order:
[bs, ind] = sort(b);
As = A(ind);
C = accumarray(bs(:), As(:), [], @(x) {x});
gives
>> C
C =
[3x1 double]
[3x1 double]
[ 4]
[2x1 double]
>> celldisp(C)
C{1} =
1
6
8
C{2} =
2
3
7
C{3} =
4
C{4} =
5
9
Upvotes: 2
Reputation: 104565
Firstly, I would not recommend you create separate variables for each array... that will simply be unwieldy. What if you have 100 different values in b
? I recommend you use a cell
array instead where each cell extracts out the corresponding values of A
.
A simple call to arrayfun
and unique
will suffice:
out = arrayfun(@(x) A(b == x), unique(b), 'uni', 0);
What this will do is for each unique value in b
, we extract out the corresponding locations in A
that match and put them into a cell array. Given your small example:
b=[1 2 2 3 4 1 2 1 4];
.... and A
is simply:
A = 1:numel(b);
I declare A
like this on purpose so it matches the actual corresponding locations of A
you are extracting... and so A(i) = i
for i = 1
up to as many values as we have b
.
We get this:
>> celldisp(out)
out{1} =
1 6 8
out{2} =
2 3 7
out{3} =
4
out{4} =
5 9
You can see that for each cell, we extract out the right values in A
corresponding to each unique ID found in b
.
If you're not familiar with arrayfun
, it basically performs a function on each value of an input array. In our case, what I want to do is specify an array to be all of the unique values in b
. For each unique value in b
, I take a look at where I can find these locations that match, then use logical indexing to extract out the corresponding values in A
.
arrayfun
is basically a for
loop, and so the equivalent for
loop code will look something like this:
unq = unique(b);
out = cell(1,numel(unq));
for idx = 1:numel(unq)
x = unq(idx);
out{idx} = A(b == x);
end
We first find all of the unique values in b
and store them in unq
, create a cell array that has as many cells as there are unique values, then for each unique value, extract out the right A
values that match a given i
value in b
.
Upvotes: 2