结构对象的平等

时间:2016-07-15 12:37:48

标签: matlab matlab-struct

我在matlab中有一个树形结构,如下所示:

node = 
  sub: [1x4 struct]

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

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

等。叶子节点有空子。假设我有一个节点,我正在遍历树。有没有办法检查节点'对象'是否与树中的任何对象相同?我不是在说价值是一样的。我希望'对象'是一样的。

例如:

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

2 个答案:

答案 0 :(得分:2)

MATLAB中的struct在技术上并不是你谈论它的意义上的“对象”。如果我创建一个结构然后将其指定为另一个结构中的字段,那么这两个现在是解耦的。对第一个结构所做的任何更改都不会反映在我们刚刚制作的副本中。

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

a.a = 3

% b.b.a == 2

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

如果您确实想要验证您所比较的两个struct是否以相同方式创建,那么可以 以递归方式通过struct并确定两个结构中每个元素的memory location是否相同。这意味着结构是相同的它们是用相同的底层数据创建的。

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

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个对象。基本类看起来像这样。

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

答案 1 :(得分:1)

如果您正在搜索&#34;参考相等&#34;我想你应该使用handle个对象:

  

如果要确定是否有不同的句柄对象,请使用isequal   在所有对象属性中具有相同的数据。如果您愿意,请使用==   确定句柄变量是否引用同一个对象。

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

正如您所看到的那样,两个grand-grand-child对象在属性方面是相同的,但输出上的Iteration step: 2条目证明,第一个曾祖父的子项被跳过,因为函数是寻找第二个。

isequal==之间的差异:

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

ans =    1

>> grandGrandChild == grandGrandChild2

ans =   0