A Doe
A Doe

Reputation: 301

Matlab unique cell combinations

I have a list as given below:

A= {[1 2], [2 1], [2 1 3],[3 4],[4 3]}

I need to simplify the matrix. For example, [3 4] and [4 3] form the same combination, only one of them is enough. Also, [1 2] and [2 1] is the same combinations, so I should be left with

newA= {[1 2],[2 1 3],[3 4]}

How do I do that?

Upvotes: 3

Views: 158

Answers (3)

rahnema1
rahnema1

Reputation: 15837

Here is a solution using accumarray:

n = cellfun(@numel,A);
C=accumarray(n(:),1:numel(A),[],@(x){num2cell(unique(sort(vertcat(A{x}),2),'rows'),2)});
result = vertcat(C{~cellfun(@isempty,C)})

I tested 3 proposed answers with the following data in Octave:

A=arrayfun(@(x){randi([1 10],1,randi([1 10000]))},1:50);

Here is the result:

======NUM2STR=======:
Elapsed time is 1.13129 seconds.
======FOR LOOP=======:
Elapsed time is 0.237398 seconds.
======ACCUMARRAY=======:
Elapsed time is 0.036804 seconds.

With the following data:

A=arrayfun(@(x){randi([1 3],1,randi([1 5]))},1:500);    

Result:

======NUM2STR=======:
Elapsed time is 0.384026 seconds.
======FOR LOOP=======:
Elapsed time is 10.9931 seconds.
======ACCUMARRAY=======:
Elapsed time is 0.0271118 seconds.

Online Demo

Upvotes: 3

Luis Mendo
Luis Mendo

Reputation: 112699

The most efficient way is probably to sort each vector and use two nested loops as follows:

As = cellfun(@sort, A, 'UniformOutput', false); % sort each vector
remove = false(size(A)); % initiallize. Entries to be removed will be marked true
for ii = 1:numel(A)
    for jj = ii+1:numel(A)
        remove(jj) = remove(jj) || isequal(As{jj}, A{ii}); % short-circuit OR
    end
end
result = A(~remove);

Upvotes: 5

sco1
sco1

Reputation: 12214

One approach is to sort the values and use unique:

A = {[1 2], [2 1], [2 1 3],[3 4],[4 3]};

tmp = cellfun(@sort, A, 'UniformOutput', false);
tmp = cellfun(@num2str, tmp, 'UniformOutput', false);
[~, idx] = unique(tmp);

newA = A(idx);

Note 1 that I've had to make a dummy array of the string equivalent of A due to unique's handling of cell arrays. unique can only work on cell arrays of strings/character vectors so we have to do a little manipulation to get the desired output.

Note 2 that cellfun is almost always slower than the explicit loop, but I've used it here for brevity.

Upvotes: 5

Related Questions