If I have an array [1 2 3 4 3 5 6 7 8 7]
, I'd like to find the list of non-unique entries: [3 7]
. I fail to find a simple way to do it. Any idea?
Update: I'd like to have a universal solution, which would also work with cell array of strings.
If I have an array [1 2 3 4 3 5 6 7 8 7]
, I'd like to find the list of non-unique entries: [3 7]
. I fail to find a simple way to do it. Any idea?
Update: I'd like to have a universal solution, which would also work with cell array of strings.
If A has length n, you can find the indices in A of the first occurrence of each entry and remove them from A:
A = [1 2 3 4 3 5 6 7 8 7];
n=length(A);
[~,IA,~] = unique(A);
out = unique(A(setdiff((1:n),IA)))
One approach with unique
and histc
-
[unqA,~,id] = unique(A);
out = unqA(histc(id,1:max(id))>1)
Or use accumarray
in place of histc
-
out = unqA(accumarray(id(:),1)>1)
Or use bsxfun
-
out = unqA(sum(bsxfun(@eq,id(:),1:max(id(:)).'))>1)
Sample runs -
1) Numeric arrays case -
>> A
A =
6 3 7 7 4 3 8 5 2 3 1
>> [unqA,~,id] = unique(A);
>> unqA(histc(id,1:max(id))>1)
ans =
3 7
>> unqA(accumarray(id(:),1)>1)
ans =
3 7
>> unqA(sum(bsxfun(@eq,id(:),1:max(id(:)).'))>1)
ans =
3 7
2) Cell arrays case -
>> A = {'apple','banana','apple','mango','ball','cat','banana','apple'};
>> [unqA,~,id] = unique(A);
>> unqA(histc(id,1:max(id))>1)
ans =
'apple' 'banana'
>> unqA(accumarray(id(:),1)>1)
ans =
'apple' 'banana'
>> unqA(sum(bsxfun(@eq,id(:),1:max(id(:)).'))>1)
ans =
'apple' 'banana'
x=[1 2 3 4 3 5 6 7 8 7];
y=x;
[~,ind,~]=unique(y);
y(ind)=[];
y is the non-unique entries.
Since you ask for a more generic solution, here is one that should be easily adaptable to other data types. Compared to others it is also a O(n) solution - but the drawback is the slow Matlab looping on large array of elements...
A = [1 2 3 4 3 5 6 7 8 7];
dupes = [];
map = containers.Map('KeyType', class(A), 'ValueType' , 'logical');
for i=1:numel(A)
if map.isKey(A(i))
dupes = [dupes A(i)];
else
map(i) = true;
end
end
Another approach using sort
and diff
:
As = sort(A);
out = unique(As([false diff(As)==0]));