How to determine if an array of objects is part of an other array of objects?

I have an array containing classdef-objects ( value class ) of the same class, but with different values for the properties.
A = [ objA, objB, objC, objD ];
Now I get another array with objects of the same class
B = [ objX, objY ];
Comparing objects with each other I can do by
isequal( objX, objA );
which returns true. Also objY is equal to objC.
Now like with numeric arrays (I think there it was any or ismember or just through vector operations) I want to do this kind of check:
isequal( A, B );
and it should return true, because all parameters I'm searching for (combined in array B) are present in A!
Using isequal on A and B returns 0 because not all objects are equal and this is the only function I found to compare objects.
Is there a secret function or workaround?
Thanks for your help! :)
EDIT:
Here is a MWE:
class 1 (prop arr contains objects of class 2)
classdef arrOfTests
properties
arr
end %properties
methods
function obj = arrOfTests()
obj.arr = test.empty;
obj.arr(1) = test( 'One', 'Test', 1 );
obj.arr(2) = test( 'Two', 2, [1,2] );
obj.arr(3) = test( 'Three', 'Test', [1,2,3] );
end %function test (Constructor)
end %methods
end %classdef
class 2 (element of array in property of class 1)
classdef test
properties
propOne
propTwo
propThree
end %properties
methods
function obj = test(propOne, propTwo, propThree)
obj.propOne = propOne;
obj.propTwo = propTwo;
obj.propThree = propThree;
end %function test (Constructor)
end %methods
end %classdef
example script to create the objects:
obj = arrOfTests();
compObj = test( 'Two', 2, [1,2] );
isequal( compObj, obj.arr ); % ans = 0; not equal
isequal( compObj, obj.arr(2) ); % ans = 1; is equal
%ismember( compObj, obj.arr ); % Error: Undefined operator '==' for input arguments of type 'test'...
%ismember( compObj, obj.arr(2) ); % Error: Undefined operator '==' for input arguments of type 'test'...
%all( ismember( compObj, obj.arr ) ); % Error: Undefined operator '==' for input arguments of type 'test'...

5 Kommentare

If I remember correctly, ismember works on any object class. What output does it return for your example? If that doesn't work, can you write a MWE so we can more easily play around with this?
Tom Wenk
Tom Wenk am 24 Mai 2018
Bearbeitet: Tom Wenk am 24 Mai 2018
I edited the question post, please have a look if the MWE is satisfying.
ismember throws an error (see my MWE)
Depending on how complex your real class is you could overload the eq operator, then ismember will work. Obviously this is a case where a minimum working example doesn't help as it is trivial to overload eq for this case where it may not be for your real case. Mind you, if you have trouble defining the equality operator on your class then Matlab would likely also have trouble anyway. You need to tell Matlab how to measure equality between two objects of a class.
You definitely don't want isequal to be working as you propose though because A and B are clearly not equal so should always return false, just like
isequal( [2 3 4 5], [2 4] )
does.
Right, isequal is not the right function for it, but it was the only function that could handle the comparison of the objects in my tries.
I want the functionality of ismember for objects! :D
all( ismember( [2, 4], [2 3 4 5] ) )
like so but with objects.
Which you can have if you overload the eq operator in your class.

Melden Sie sich an, um zu kommentieren.

 Akzeptierte Antwort

You can do this using this statement
all(cellfun(@(x) any(x), arrayfun(@(x) arrayfun(@(y) isequal(x, y), A), B, 'UniformOutput', 0)'))
This will check whether all the values of B are present in A.

4 Kommentare

It seems to work, thanks a lot!
Nevertheless I will need some time to figure out what is happening there! :D
Does this also work, when there are different objects of different classes in a cell-array?
You are welcome. Actually, this is just some for loops written in compact form. You can get the same result with for loops. Yes, it will if both A and B are cell arrays. Even if they have elements of different classes if each element of B is present in A, it will return true.
What it does is perfect, but is there also an other way to get there besides using for-loops?

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Try:
all(ismember(A, B))

4 Kommentare

ismember doesn't work here, I got the error:
Undefined operator '==' for input arguments of type 'test'...
Note: I added a MWE to my question
== is not working, but isequal does. As suggested already, overloading the eq operator would solve this:
% Define eq as
isequal(A, B)
Tom Wenk
Tom Wenk am 24 Mai 2018
Bearbeitet: Tom Wenk am 24 Mai 2018
Could you change my MWE and add the overloaded operator please?
I tried to do it, but I failed. For me ismember now doesn't throw an error anymore, but it still does not tell me that A is a member of B (return parameter 0)!
And is this a cleaner/faster solution (not a compact form of nested for-loops) than the one given by Ameer Hamza (which is working perfectly)? :D
Because I do not know, what the properties of your class are, while you have the class definition available already, it would be a waste of time, if I re-write what I guess might solve your problem. Please be so kind and post the MWE by your own. [EDITED - ah, I've found your code, thanks.]
I cannot estimate, if ismember with an overloaded eq is faster, but of course it would be nice and intuitive. Note that setdiff, setxor, unique and union might work directly also directly. Having a powerful implementation of the class, which works fluently with all the standard tools provided by Matlab, would be a great advantage. Perhaps a specific cellfun/arrayfun/arrayfun approach is some microseconds faster (but arrayfun is usually slower than a simple FOR loop!), having the standard set function can save you minutes or hours of programming and debug time.
On the other hand, a dedicated function could be much faster: all(ismember()) checks all elements. But if the first one is not matching already, most of the time is lost. I'd start with a loop:
function T = ContainsAll(A, B)
T = true;
nB = numel(B);
for iA = 1:numel(A)
AA = A.arr(iA);
for iB = 1:numel(B)
if ~isequal(AA, B.arr(iB))
T = false;
return;
end
end
end
end
Darn. I'm too tired to work. This is a function. Of course a method would be nicer, because this is OOP. Sorry.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Construct and Work with Object Arrays finden Sie in Hilfe-Center und File Exchange

Gefragt:

am 23 Mai 2018

Kommentiert:

Jan
am 24 Mai 2018

Community Treasure Hunt

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

Start Hunting!

Translated by