2

I have a m-by-1 matrix, A. I want to find out which elements are duplicates and get their row values. (Just the row values because the matrix is m-by-1.)

I've tried

k = find(~unique(A));

but k contains the wrong values.

Here's an example of what I'm trying to do. Consider the array A;

A = [4
     5
     5
     5
     7
     8
     4];

Since 4 and 5 are the repeated elements here, I would like to get the row values of these elements and put them in a new array. The resulting array would be

RowValues= [1
            2
            3
            4
            7];

Note: The above is just an example and the actual array I am dealing with contains rational numbers of the type -0.0038, 1.3438 and so on in the array A.

Matte
  • 339
  • 2
  • 19
  • When you try `unique(A)`, think (or read the doc) what `~` would do to it – Sardar Usama May 19 '18 at 06:19
  • Related [this](https://stackoverflow.com/questions/40393513/eliminate-remove-duplicates-from-array-matlab) and [this](https://stackoverflow.com/questions/48645621/deleting-non-unique-rows-from-an-array) – rahnema1 May 19 '18 at 07:20

2 Answers2

4

Here is a solution using intersect:

s = sort(A);
c = intersect(s(1:2:end),s(2:2:end));
RowValues = find(ismember(A,c));

I have compared this method with the method proposed by @SardarUsama with a large [1 x 10000000] input in Octave. Here is the result:

=======INTERSECT==========
Elapsed time is 1.94979 seconds.

=======ACCUMARRAY==========
Elapsed time is 2.5205 seconds.
rahnema1
  • 15,264
  • 3
  • 15
  • 27
  • 1
    It took me some time to understand the input arguments of intersect. That's clever, I must say. – Sardar Usama May 19 '18 at 07:03
  • I've run this code as it is but it's skipping over some elements in the array. I should have mentioned this but does this code work for positive and negative fractional numbers as well? I'm sorry, I'll edit my question to reflect that. – Matte May 19 '18 at 07:22
  • Its result is the same as the method provided by other answer. You can compare them [online](http://rextester.com/EXLJM47941) – rahnema1 May 19 '18 at 07:24
  • @Matte The elements in your array that you consider same are not *really* same. Read [***this***](https://stackoverflow.com/questions/686439/why-is-24-0000-not-equal-to-24-0000-in-matlab) and [***this***](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) for the insight. – Sardar Usama May 19 '18 at 07:29
  • 1
    @Sardar Usama Yes, I'd only been seeing a part of the number. I rounded off the digits and now I'm getting the right answer, thank you :) – Matte May 19 '18 at 07:32
2

Find the count of each element of A using unique and accumarray, filter out the non-repeating values, use ismember to get the logical indices of repeating values and then use find to convert them to linear indices.

[C, ~, ic] = unique(A);    
RowValues = find(ismember(A, C(accumarray(ic,1)>1)));

Why you get the wrong indices with your code?
Applying logical NOT on the vector of unique values would convert them to a logical vector containing true at the index where unique value is zero and false where it is non-zero and hence finding the non-zero (false in this case) elements of such a vector would lead nowhere.

Sardar Usama
  • 19,536
  • 9
  • 36
  • 58