2016-07-15 70 views
3

我在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

在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 
+0

我錯過了這一點。這就是爲什麼我的樹修改代碼不起作用。你知道如何做遍歷樹和修改它嗎?我發現最近的是這樣的: http://stackoverflow.com/questions/14793453/matlab-link-to-variable-not-variable-value – TyanTowers

+1

@TyanTowers爲什麼不讓你的節點成爲實際的'handle'對象? – Suever

1

如果您正在尋找「參考平等」我猜你應該使用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。米

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