How to get a unique array value in Matlab? - matlab

I have array value like this snippet below:
a = { [1 2 4]; [3 5 6 7]; [1 2 4]; [3 5 6 7]; [8 9]; []};
I am trying Matlab to get array value like this
a = { [1 2 4]; [3 5 6 7];[8 9]};

basic solution for finding uniques
unique(cellfun(#(x)(mat2str(x)),a,'uniformoutput',false))
This can be found here actually.
Complicating factors
Technically the empty cell at the end is also unique, perhaps you want to remove it separately like so:
a(cellfun(#isempty,a)) = []
Currently you get strings as output, this can be solved like so:
[~, idx] = unique(cellfun(#(x)(mat2str(x)),a,'uniformoutput',false))
a(idx)
I personally think that this is harder than it should be.
Summary
You can get your desired output like so
a(cellfun(#isempty,a)) = []
[~, idx] = unique(cellfun(#(x)(mat2str(x)),a,'uniformoutput',false))
a(idx)

Related

MATLAB: How do I combine a structure array with same size field values into one structure

I have a structure array where each field of the same name is the same size. I want to combine each field over the array into one field. For example:
A(1).x = [1 2 3];
A(1).y = [4 5 6];
A(2).x = [7 8 9];
A(2).y = [10 11 12];
I want the new structure to be
B.x = [1 2 3;
7 8 9];
B.y = [4 5 6;
10 11 12];
These could also be a cell of structures if that makes things easier.
A.x produces a comma-separated list of values. You can use this comma-separated list in a function call, in which case each value is treated as a separate argument. This is very useful, as you can pass it into a call to cat to concatenate the values:
B.x = cat(1, A.x);
You'd have to do this same operation for each of the fields. To automate this you could iterate over fieldnames(A):
for name = fieldnames(A).'
B.(name{1}) = cat(1, A.(name{1}));
end

Fast way of concatenating complex data using vertcat with custom rows

I need to concatenate few bigger matrices, but in specific manner - for example to concatenate only 1 row from X matrices.
There is a good solution of storing the data in a structure, so then there is no need of preparing long list of things that needs to be concatenated.
For example, we will have a structure like that:
struct(1).huge = [1 2 3 4; 1 2 3 4];
struct(2).huge = [1 2 3 4; 1 2 3 4];
struct(3).huge = [1 2 3 4; 1 2 3 4];
Then we can concatenate these with:
concatVar.concat = vertcat(struct.huge);
Instead of, for example:
concatVar.concat = vertcat(struct(1), struct(2),(...),struct(100));
But what if I need to concatenate only specific rows from different fields in the structure, for example only 1 row:
concatVar.concat = vertcat(struct.huge(1,:));
Then this method will not work, with the error:
"Expected one output from a curly brace or dot indexing expression, but there were X results".
Is it even possible of doing something like that in a fast and reliable way with use of vertcat or horzcat?
Thanks for any advice!
BM
It seems hard to avoid a loop in this case. You can convert the struct's field into a cell and then use cellfun, which is essentially a loop.
Let your struct be defined as follows. Note that it's not advised to use function names or reserved words like struct as variable names.
s(1).huge = [1 2 3 4; 1 2 3 4];
s(2).huge = [1 2 3 4; 1 2 3 4];
s(3).huge = [1 2 3 4; 1 2 3 4];
Then:
result = cell2mat(cellfun(#(x) x(1,:), {s.huge}, 'uniformoutput', false).');

Given a cell array of vectors, delete vectors that are subsets of any other vector

I wanna delete all the subsets of cell c, suppose I have 6 cell vectors: c{1}=[1 2 3]; c{2}=[2 3 4];
c{3}=[1 2 3 4 5 6]; c{4}=[2 3 4 7]; c{5}=[2 3 7]; c{6}=[4 5 6]; then I wanna delete [1 2 3], [2 3 4] and [4 5 6]. I used two for loops to find all these subsets, but it's too slow for large datasets, is there any simple way can do this?
The following code removes a vector if it's a subset of any other vector. The approach is very similar to my answer to this other question:
n = numel(c);
[i1 i2] = meshgrid(1:n); %// generate all pairs of cells (their indices, really)
issubset = arrayfun(#(k) all(ismember(c{i1(k)},c{i2(k)})), 1:n^2); %// subset?
issubset = reshape(issubset,n,n) - eye(n); %// remove diagonal
c = c(~any(issubset)); %// remove subsets
Note that, in your example, [2 3 7] should also be removed.
You could find the cells that are exact matches for a particular input vector s1 using the following approach:
indx = find(cell2mat(cellfun(#(x)strcmp(num2str(x),num2str(s1)),c,'un', 0)));
You can then loop over matches (which should now be a much smaller set), and remove them by setting their contents to an empty set:
for ii=1:length(indx)
c{:,ii} = [];
end

How to use multidimensional constant array in for iterator block in matlab/simulink?

I have an array (300x6) and I want to use it for this block in simulink. But I have a problem. How can I use "for iterator" block to take the q(i,:), q(i+1,:) , q(i+2,:) ... elements respectively? Or is there any other way to do this idea? Thanks.
In Matlab, for iterates over matrix columns. So you can just transpose to iterate over rows:
A = [1 2 3; 4 5 6; 7 8 9]; %// example matrix
for v = A.'
v = v.'; %// v will be [1 2 3], then [4 5 6] etc
%// Do stuff with v
end
I'm not into Simulink but I guess you can adapt this to that environment.

use 2Xn matrix entries as indices

Is it possible to use matrix entries as indices to other matrix ?
for example :
A=[1 2 ; 4 5 ; 6 7 ];
And I want to reach entries of other matrix using A, without using loops.
Othermat(1,2), Othermat(4,5) %...
If yes how can I do it ?!
Sure, use sub2ind:
A = [1 2; 4 5; 6 7];
ind = sub2ind(size(Othermat),A(:,1),A(:,2));
values = Othermat(ind);
The suggested sub2ind is a natural way to generate indices.
Of course it is also not very hard to find the linear index directly:
A = [1 2; 4 5; 6 7];
Othermat = magic(7);
Othermat(A(:,1)+(A(:,2)-1)*size(Othermat,1))