Matlab: Creating maps of groups and indicies of duplicates in an array - arrays

I have two Matlab arrays A(containing groups of numbers) and B(containing values that belong to the groups in A), there are repeats in array A
A = [1 1 1 2 2 3 4 4 4 4 4]
B = [1 2 3 3 5 4 4 1 6 7 8]
Now i would like to get the following two maps:
C = ['1': {1,2,3}, '2': {3,5}, '3':{4}, '4':{1,6,7,8}]
where C gives a map with the group number as index and related values in that particular group.
D = ['1':{2,4},'2':{1},'3':{4},'4':{1}]
Where D gives a map with the group number from A as index. The values are the group numbers from A for which there are repeated values in B for that particular sub group.
What is the most efficient way of dealing with this problem? Are maps a good data structure to store this kind of data. I know the first one can be dealt with a for loop which i would like to avoid.

I don't understand how you get to D.
For C, you can use accumarray:
C = accumarray(A,B,[],#(x){x})
C{1} is [1 2 3]

Related

MATLAB - Get every N elements in a vector

I have an array
a = [1 2 3 4 5 6 7 8]
I want to get every group of 4
so the result is as such
[1 2 3 4]
[5 6 7 8]
I do not know how many elements there will be but I know it is divisible by 4
so something like a(1:4) and a(5:8) wont work, I can use a loop, but is there a way to not use a loop?
For an unknown number of elements in a you can use reshape you just need to figure out how many rows you will have in the final matrix or (better for your case) the number of columns.
a = 1:4*10;
a2 = reshape(a, 4, []).';
If you went the rows routine you would do this.
a = 1:4*10;
a2 = reshape(a, [], numel(a) / 4).';
You just need to be sure that a has the proper number of elements. numel simply tells you the total element count.

MATLAB - extract array values based on conditions

I have 4x4 matrix A
[1 2 3 4;
2 2 2 3;
5 5 5 5;
4 4 4 4]
I know how to locate all values less than 4. A<4. But I'm not sure how to write an 'if' statement for; three or more values, all which are less than 4, contained in the same row. For instance; see above A(1,:) and A(2,:) satisfies my conditions.
You can basically do A<4 to know which ones are smaller. If you want to know which rows contain N values smaller than 4 then you can do
rows=find(sum(A<4,2)>=3)
This basically does:
find smaller than 4
Count how many of them in each row (sum(_,2))
find if they are 3 or more
give the row index of those find()

How to sort one array and use the order to sort a second array in MATLAB

Suppose i have two arrays
a=[4 3 6 1 7 8]
b=[3 5 1 8 4 6]
I need to sort b in the same order as a, which will be sorted in ascending order
ie.,
first sorting a
a=[1 3 4 6 7 8]
whose corresponding indices will be [4 2 1 3 5 6]
and using this indices, i have to sort b, ie.,
b=[8 5 3 1 4 6]
how do i do this in MATLAB
see the 2nd output of sort
[sortedArray,sortedIndex] = sort(a)
b(sortedIndex)
The second output of sort describes the ordering of the elements. See doc sort
[aSrt, ind] = sort(a);
bSrt = b(ind);

Find elements in array those have come two times in array

Given A = [3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 8]
Output B = [3 4 5 6 8]
Is there a Matlab function or command to get this result? I am new to Matlab. Just now I am doing it going through for each element and keeping a counter for it. I have very big array so this is taking too much time.
Use a combination of unique and histc:
uA = unique(A); %// find unique values
B = uA(histc(A, uA)>=2); %// select those that appear at least twice
The above code gives the values that appear at least twice. If you want values that appear exactly twice, replace >= by ==.

Easiest way to create arrays based on repeating character positions

I want to group my elements using the repeated segments in the array. The breaking is basically depend on where the repeated segments are, in my real data contains ~10000 elements and I want to know if there is a easier way to do that.
Here is a short example to clarify what I want:
Let's say I have an array,
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
What I want is to break A into [1 5 3],[6 9], and [9 5 2];
What is the easiest to code this using matlab??
Thanks.
For a vectorized solution, you can find out the places where either forward or backward differences to the neighbor are zero, and then use bwlabel (from the Image Processing Toolbox) and accumarray to gather the data.
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
d = diff(A)==0;
%# combine forward and backward difference
%# and invert to identify non-repeating elments
goodIdx = ~([d,false]|[false,d]);
%# create list of group labels using bwlabel
groupIdx = bwlabel(goodIdx);
%# distribute the data into cell arrays
%# note that the first to inputs should be n-by-1
B = accumarray(groupIdx(goodIdx)',A(goodIdx)',[],#(x){x})
EDIT
Replace the last two lines of code with the following if you want the repeating elements to appear in the cell array as well
groupIdx = cumsum([1,abs(diff(goodIdx))]);
B = accumarray(groupIdx',A',[],#(x){x})
EDIT2
If you want to be able to split consecutive groups of identical numbers as well, you need to calculate groupIdx as follows:
groupIdx = cumsum([1,abs(diff(goodIdx))|~d.*~goodIdx(2:end)])
Here is a solution that works if I understand the question correctly. It can probably be optimised further.
A=[1 5 3 4 4 4 6 9 8 8 9 5 2];
% //First get logical array of non consecutive numbers
x = [1 (diff(A)~=0)];
for nn=1:numel(A)
if ~x(nn)
if x(nn-1)
x(nn-1)=0;
end
end
end
% //Make a cell array using the logical array
y = 1+[0 cumsum(diff(find(x))~=1)];
x(x~=0) = y;
for kk = unique(y)
B{kk} = A(x==kk);
end
B{:}

Resources