结构对象的相等性

Equality of structure objects

我在matlab中有这样一个树结构:

node = 
  sub: [1x4 struct]

其中每个子节点也是一个节点。

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

等叶节点有空子。假设我有一个节点并且我正在遍历树。有什么方法可以检查节点 'object' 是否与树中的任何节点相同?我不是在谈论价值相同。我希望 'object' 相同。

例如:

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

A struct 在 MATLAB 中从技术上讲并不是您所说的 "object"。如果我创建一个结构,然后将其分配为另一个结构中的一个字段,则两者现在是解耦的。对第一个结构所做的任何更改都不会反映在我们刚刚制作的副本中。

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

a.a = 3

% b.b.a == 2

您实际上只能可靠地检查两个 struct 是否相等。

如果您真的想验证您正在比较的两个 struct 是以相同的方式创建的,您 可以 通过 struct 并确定每个元素的 在两个结构中是否相同。这意味着该结构既 它们是使用相同的基础数据创建的。

对于一个非常简单的非深层嵌套结构,它可能看起来像这样。

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

更新

另一种方法是为您的节点使用实际的 handle 对象。基本的 class 看起来像这样。

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

如果您要搜索 "reference-equality",我想您应该使用 handle 个对象:

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

输出为

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

如您所见,两个曾孙对象在属性方面是相等的,但是输出中的 Iteration step: 2 条目证明第一个曾孙对象被跳过了,因为函数正在搜索第二个。

isequal==的区别:

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

ans =    1

>> grandGrandChild == grandGrandChild2

ans =   0