Can we do something like this similar to union()?

Currently union() returns non-repeated result. But I want repeat result like the following,
>> myunion([2 3 3 5], [1 3 5])
ans =
1 2 3 3 5
I can write for-loop and if-statement to do this. But is there a better or easy way?
Thanks Kevin

4 Kommentare

Stephen23
Stephen23 am 10 Feb. 2018
Bearbeitet: Stephen23 am 10 Feb. 2018
@Kevin: what should the output of this be?:
myunion([2,3,3,5,1,9,2], [1,3,5,9,1])
What about?:
myunion([1,2,3,5],[1,2,3,4])
John D'Errico
John D'Errico am 10 Feb. 2018
Bearbeitet: John D'Errico am 10 Feb. 2018
You need to explain exactly what you goal is here. One ambiguous example does not cut it. Well, one example, might suffice if it was at least consistent.
In your example, where did the multiple copies of 3 arise (but only TWO, not three of them!), but not two copies of the number 5?
Kevin's "Answer" moved here:
Sorry, my fault. I should be more specific in my first post.
>> myunion([2 3 3 5], [1 3 5])
ans =
1 2 3 3 5
  • The first element (in the output vector) is 1 because the second input vector has a 1.
  • The second element (in the output vector) is 2 because the first input vector has a 2.
  • The third and forth elements (in the output vector) are 3 because the first input vector has [3 3]. Now if first input vector has [3 3 3], then output vector vector should have three 3's, i.e. I want the output vector should have the repeated elements (number of repeated elements = maximum of the number of elements in either input vector).
So MATLAB's union() is almost perfect except that it does not returned the repeated elements.
>> union([2 3 3 5], [1 3 5])
ans =
1 2 3 5
union() would be perfect if the output vector has two 3's since the first input vector has 2 3's.
Hope this is clear.
Kevin
John D'Errico
John D'Errico am 11 Feb. 2018
Bearbeitet: John D'Errico am 11 Feb. 2018
I'm a bit confused by the logic in what you want. As you wrote it, you want
myunion([2 3 3 5], [1 3 5])
to return the vector [1 2 3 3 5]. But by extension, if you simply swapped the arguments, calling it as
myunion([1 3 5], [2 3 3 5])
then it would return [1 2 3 5].
SHIVER. This is just asking to create the code from hell, i.e., code that will create all sorts of strange bugs, arising from that non-symmetrical behavior. Any code that claims to be a union should also be symmetrical in the arguments.
My personal prediction is that this code will soon be the source of a new, frenzied post, "Why do I have this strange bug in my code? Forewarned is forearmed. :)

Melden Sie sich an, um zu kommentieren.

 Akzeptierte Antwort

Stephen23
Stephen23 am 11 Feb. 2018
Bearbeitet: Stephen23 am 13 Feb. 2018

0 Stimmen

Method one: unique, arrayfun, ones:
>> A = [2,3,3,5];
>> B = [1,3,5];
>> fun = @(n)n*ones(1,max(nnz(A==n),nnz(B==n)));
>> C = arrayfun(fun,unique([A(:);B(:)]),'uni',0);
>> U = [C{:}]
U =
1 2 3 3 5
Note: the arrayfun call is just for convenience, not for speed!
Method two: unique, histc, repelem:
>> A = [2,3,3,5];
>> B = [1,3,5];
>> Q = unique([A(:);B(:)].');
>> repelem(Q,max([histc(A,Q);histc(B,Q)]))
ans =
1 2 3 3 5

3 Kommentare

Kevin
Kevin am 11 Feb. 2018
Hi Stephen,
Great. That works.
Thank you. Kevin
Hi Stephen,
You are brilliant. Thank you for your idea on using HIST. Your method 2 is very elegant and much faster.
Found a corner case that breaks method 2,
A = [3 3]; B = [3 3 3];
This causes problem into the call of HIST because Q is a scalar and treated as number of bins. So use HISTC instead.
Fix:
Q = unique([A(:); B(:)].');
U = repelem(Q, max([histc(A, Q); histc(B, Q)]));
Thank you very much for your idea. Kevin
Stephen23
Stephen23 am 13 Feb. 2018
Bearbeitet: Stephen23 am 13 Feb. 2018
@Kevin: thank you for the feedback. I will include your suggested fix into my answer (for future readers).

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

John D'Errico
John D'Errico am 10 Feb. 2018
Bearbeitet: John D'Errico am 10 Feb. 2018

0 Stimmen

My guess is that your ambiguous example was not even representative of your problem, given your words. So let me guess and try to answer your words. :)
Your words said that you want the union, but one that allows repeats. In that case it should have produced:
myunion([2 3 3 5], [1 3 5])
ans =
1 2 3 3 3 5 5
since there were 3 copies of the number 3, and 2 copies of the number 5.
If so, then the answer is trivial.
myunion = @(X,Y) sort([X,Y]);
You might need to worry about the orientation of the vectors, in case they might be row OR column vectors or both. But that is an easy change.

Kategorien

Mehr zu Programming finden Sie in Hilfe-Center und File Exchange

Produkte

Tags

Gefragt:

am 10 Feb. 2018

Bearbeitet:

am 13 Feb. 2018

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by