Reputation: 53
I have two arrays:
A=[1 1 2 2 3 3 3];
B=[1 3];
Is there any function that can remove elements which are contained in B
from A
?
The result should be
C=[1 2 2 3 3];
The order is not important, but if there is more specific elements like two times 1
in A
, then I need operation that removes (from A
) only as many of these specific elements is in B
(in this case only one of 1
and one of 3
; meaning other 1
and 3
should remain in final product C
). This function should be analogous to setdiff
, with the difference that it should take care of multiple instances of array elements. This analogy can hold because my B
only contains elements that are in A
.
Upvotes: 4
Views: 871
Reputation: 125864
Here's a vectorized solution using accumarray
and repelem
:
maxValue = max([A B]);
counts = accumarray(A(:), 1, [maxValue 1])-accumarray(B(:), 1, [maxValue 1]);
C = repelem(1:maxValue, max(counts, 0));
And the result for your sample data A = [1 1 2 2 3 3 3]; B = [1 3];
:
C =
1 2 2 3 3
This will even work for cases where there are values in B
not in A
(like B = [1 4];
) or more of a given value in B
than in A
(like B = [1 1 1];
).
Note: The above works sinceA
and B
contain integers. If they were to contain floating-point values, you could map the unique values to integers first using unique
and ismember
. Let's say we had the following sample data:
A = [0 0 pi pi 2*pi 2*pi 2*pi];
B = [0 2*pi];
Here's a variant of the above code that can handle this:
uniqueValues = unique([A B]);
[~, A] = ismember(A, uniqueValues);
[~, B] = ismember(B, uniqueValues);
maxValue = max([A B]);
counts = accumarray(A(:), 1, [maxValue 1])-accumarray(B(:), 1, [maxValue 1]);
C = uniqueValues(repelem(1:maxValue, max(counts, 0)));
And the results:
C =
0 3.1416 3.1416 6.2832 6.2832 % [0 pi pi 2*pi 2*pi]
Upvotes: 1
Reputation: 45752
For loop solution:
C = A;
for ii = 1:length(B)
C(find(C == B(ii), 1,'first')) = [];
end
Result
C =
1 2 2 3 3
Upvotes: 4