Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split vector into several vectors depending on its content

I have a vector that I know will consist of the values 100, 200 and 400. The values will not be mixed up but be it order, for example

target = [100 100 100 100 200 200 400 400 400];

I want to split this vector up into three vectors, each vector containing all the values of that kind.

A = [100 100 100 100];
B = [200 200];
C = [400 400 400];

The length of target will change from time to time and so will the proportion of 100, 200 and 400.

How can I make this split in an easy way?

My own solution looks like this but I was thinking that there is another way that requires less code.

columns = size(target, 2);

A = [];
B = [];
C = [];
% Splitting target into groups
for j = 1:columns
    if target(1, j) == 100
        A = [A, 100];
    elseif target(1, j) == 200
        B = [B, 200];
    elseif target(1,j) == 400
        C = [C, 400];
    end
end
like image 950
maxala Avatar asked Sep 07 '26 04:09

maxala


2 Answers

Something simpler:

target=[100 100 100 100 200 200 400 400 400];

A = target(target==100)
B = target(target==200)
C = target(target==400)

How this works: target==x returns a logical array of size equal to target. Then you can use that logical array to index target.

like image 172
Sébastien Dawans Avatar answered Sep 09 '26 19:09

Sébastien Dawans


A little more generic approach:

%// find and count unique elements
[a,b] = hist(target,unique(target));

%// Create vectors according to target and number occurences and store them in cell array
temp = arrayfun(@(x,y) y*ones(x,1),a,b,'uni',0)

an alternative and probably faster approach would be:

%// get indices of unique values
[~,~,c] = unique(target)
%// Create vectors according to indices and store them in cell array
temp = accumarray(c(:),target(:),[],@(x) {x})

I personally would recommend you to stop at this point and continue with the cell array!

If you know how many unique elements there are and you really want to store them in separate variables, you can use:

[A,B,C] = temp{:}

The most generic and error prone approach I could think of, would be:

%// create a map container with all values you're expecting and it's corresponding specifier
valueSet =   {'A', 'B', 'C'};
keySet = [100 200 400];
mapObj = containers.Map(keySet,valueSet)

%// create a struct and distribute keys to specifier
for ii = 1:numel(keySet);
   out.(mapObj(keySet(ii))) = target(target == keySet(ii));
end

You get a struct out with the fields A, B and C:

The interesting part is, that you could also generate the keySet and valueSet automatically:

%// keySet are all unique values of target
keySet = unique(target)
%// create specifiers according to number of unique elements
valueSet = cellstr(char(65:65+numel(keySet)-1).') %'
%// you get 'A' 'B' and 'C' to use as field names

This way you don't need to know which are your elements and how many different ones you actually have. The only difference to your original request is that you don't get the variables A, B and C but out.A, out.B and out.C

enter image description here

like image 31
Robert Seifert Avatar answered Sep 09 '26 19:09

Robert Seifert



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!