Equality of structure objects

喜夏-厌秋 提交于 2019-12-10 18:57:50

问题


I have a tree structure in matlab like this:

node = 
  sub: [1x4 struct]

where each sub is also a node.

node.sub(1) = 
   sub: [1x4 struct]

etc. with leaf nodes having empty sub. Suppose I have a node and I am traversing down the tree. Is there any way to check if the node 'object' is the same as any in the tree? I am not talking about the value being the same. I want the 'object' to be the same.

For eg.:

mynode = tree.sub(1).sub(1);
isobjectequal(mynode, tree.sub(1).sub(1))

回答1:


A struct in MATLAB is not technically an "object" in the sense that you're talking about it. If I create a struct and then assign it as a field within another struct, the two are now uncoupled. Any changes made to the first struct will not be reflected in the copy we just made.

a = struct('a', 2);
b = struct('b', a);

a.a = 3

% b.b.a == 2

You can really only reliably check that the values of two structs are equal.

If you actually want to verify that the two structs that you're comparing were created in the same way, you could go through the struct recursively and determine whether the memory location of each element is the same in both structs. This would imply that the struct is both equal and they were created with the same underlying data.

For a very simple non-deeply nested struct this could look something like this.

function bool = isSameStruct(A, B)

    fmt = get(0, 'Format');

    format debug;
    memoryLocation = @(x)regexp(evalc('disp(x)'), '(?<=pr\s*=\s*)[a-z0-9]*', 'match');

    if isequaln(A, B)
        bool = true;
    elseif ~isequal(sort(fieldnames(A)), sort(fieldnames(B)))
        bool = false;
    else
        fields = fieldnames(A);

        bool = true;

        for k = 1:numel(fields)
            if ~isequal(memoryLocation(A.(fields{k})), memoryLocation(B.(fields{k})))
                bool = false;
                break;
            end
        end
    end

    format(fmt);
end

Update

An alternative is to use actual handle objects for your nodes. A basic class would look like this.

classdef Node < handle
    properties
        Value
        Children
    end

    methods
        function self = Node(value)
            self.Value = value;
        end

        function addChild(self, node)
            self.Children = cat(2, self.Children, node)
        end
    end
end



回答2:


If you are searching for "reference-equality" I guess you should use handle objects:

Use isequal when you want to determine if different handle objects have the same data in all object properties. Use == when you want to determine if handle variables refer to the same object.

treeTest.m

function treeTest()

root = TreeItem('Root');
child = TreeItem('Child');
grandChild = TreeItem('GrandChild');
grandGrandChild = TreeItem('GrandGrandChild');
grandGrandChild2 = TreeItem('GrandGrandChild');
root.Children{end+1} = child;
child.Children{end+1} = grandChild;
grandChild.Children{end+1} = grandGrandChild;
grandChild.Children{end+1} = grandGrandChild2;

findItem(root, grandGrandChild2)

    function findItem(tree, childToFind)
        if ~numel(tree.Children)
            return;
        end
        disp(['Traversing in ', tree.Name]);
        for i=1:numel(tree.Children)
            disp(['Iteration step: ', num2str(i)])
            if tree.Children{i} == childToFind
                disp(['Found! Name is ', tree.Children{i}.Name]);
                return;
            end
            findItem(tree.Children{i}, childToFind);

        end
    end
end

TreeItem.m

classdef TreeItem < handle
    properties
        Name;
        Children;
    end

    methods
        function obj = TreeItem(name)
            obj.Name = name;
            obj.Children = {};
        end 
    end
end

The output is

Traversing in Root
Iteration step: 1
Traversing in Child
Iteration step: 1
Traversing in GrandChild
Iteration step: 1
Iteration step: 2
Found! Name is GrandGrandChild

As you can see the two grand-grand-child object are equal in terms of properties, but the Iteration step: 2 entry on the output proves, that the first grand-grand-child was skipped, because the function is searching for the second one.

The difference between isequal and ==:

>> grandGrandChild = TreeItem('GrandGrandChild');
grandGrandChild2 = TreeItem('GrandGrandChild');
>> isequal(grandGrandChild, grandGrandChild2)

ans =    1

>> grandGrandChild == grandGrandChild2

ans =   0


来源:https://stackoverflow.com/questions/38396319/equality-of-structure-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!