2016-07-15 5 views
3

J'ai une structure arborescente dans Matlab comme ceci:égalité des objets la structure

node = 
    sub: [1x4 struct] 

où chaque sous est également un nœud.

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

etc. avec des nœuds de feuille ayant des sous vides. Supposons que j'ai un nœud et que je traverse l'arbre. Existe-t-il un moyen de vérifier si le noeud 'objet' est le même que celui de l'arbre? Je ne parle pas de la valeur étant la même chose. Je veux que 'l'objet' soit le même.

Pour exemple .:

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

Répondre

2

A struct dans Matlab est pas techniquement un « objet » dans le sens que vous en parlez. Si je crée une structure, puis l'affecte comme un champ dans une autre structure, les deux sont maintenant découplés. Toute modification apportée à la première structure ne sera pas reflétée dans la copie que nous venons de faire.

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

a.a = 3 

% b.b.a == 2 

Vous pouvez vraiment seulement vérifier de manière fiable que les valeurs de deux struct s sont égaux.

Si vous voulez vraiment vérifier que les deux struct s que vous comparez ont été créés de la même manière, vous pourrait passer par le struct récursive et déterminer si le memory location de chaque élément est le même dans les deux struct . Cela impliquerait que la structure est à la fois et ils ont été créés avec les mêmes données sous-jacentes.

Pour une structure très simple, non imbriquée profondément, cela pourrait ressembler à ceci.

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 

Mise à jour

Une alternative est d'utiliser des objets réels handle pour vos noeuds. Une classe de base ressemblerait à ceci.

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

J'ai raté cela. C'est pourquoi mon code de modification d'arbre ne fonctionne pas. Savez-vous comment faire quelque chose comme traverser un arbre et le modifier? Le plus proche que j'ai trouvé est le suivant: http://stackoverflow.com/questions/14793453/matlab-link-to-variable-not-variable-value – TyanTowers

+1

@TyanTowers Pourquoi ne pas faire de vos noeuds des objets 'handle'? – Suever

1

Si vous êtes à la recherche de « référence égalité » Je suppose que vous devez utiliser handle objets:

Utilisez IsEqual lorsque vous souhaitez déterminer si différents objets poignée ont les mêmes données dans tous les objets Propriétés. Utilisez == lorsque vous voulez déterminer si les variables de poignée se réfèrent au même objet.

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 

La sortie est

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 

Comme vous pouvez voir les deux objets grand-grand-enfant sont égaux en termes de propriétés, mais l'entrée Iteration step: 2 sur la sortie prouve que le premier arrière-petit-enfant a été sauté, parce que la fonction recherche le second.

La différence entre isequal et ==:

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

ans = 1 

>> grandGrandChild == grandGrandChild2 

ans = 0