How is "best" defined here? If you wan't fastest, and shortest, I have two options for you. This following code also works with both locals and globals, and avoids the bug of using $PIECE() to trim off the global/local name which won't work on globals which contain a "(" in their namespace (admittedly unlikely).
This is the fast version:
; $$FDQ($NAME(a),$NAME(b))
; Find first different nodes in two trees (or subtrees). Will
; work with locals or globals, except locals of the form % or
; %<digit>. Returns a string containing the two references where
; the first difference separated by "'=". If a node is found in
; one tree that is not present in the other, the missing
; reference is replaced by a question mark ("?"). If both trees
; are the same, an empty string is returned.
;
FDQ(%1,%2) ; [10]
NEW %3,%4,%5,%6,%7,%8,%9,%0,% ; [20]
SET %3=$DATA(@%1,%5)#10,%4=$DATA(@%2,%6)#10
QUIT:%3'=%4||(%3&&(%5'=%6)) $S(%3:%1,1:"?")_"'="_$S(%2:b,1:"?") ; [30]
SET %7=%1,%8=%2,%3=$QLENGTH(%1),%4=$QLENGTH(%2)
lq SET %1=$QUERY(@%1,1,%5),%2=$QUERY(@%2,1,%6) ; [40]
SET:%1'=""&&(%7'=$NAME(@%1,%3)) %1="" ; [50]
SET:%2'=""&&(%8'=$NAME(@%2,%4)) %2=""
QUIT:%1="" $SELECT(%2="":"",1:"?'="_%2) QUIT:%2="" %1_"'=?" ; [60]
FOR %=1:1 SET %9=$QS(%1,%3+%),%0=$QS(%2,%4+%) Q:%9'=%0 Q:%9="" ; [70]
IF %9="",%0="" GOTO:%5=%6 lq QUIT %1_"'="_%2 ; [80]
QUIT:%9]]%0 "?'="_%2 QUIT %1_"'=?" ; [90]
; ------------
; [10] %1,%2 Reference to nodes under test.
; [20] %3,%4 Upto [30] used for Do %1,%2 exist (respectively)?
; After [30] used for count of subscripts of %1,%2.
; %5,%6 Values of %1,%2.
; %7,%8 Copies of %1,%2 used to help find end subtree.
; %9,%0 First different subscript of %1,%2.
; % Loop index for scanning down subscript list.
; [30] Return if the existence of %1 and %2 differ or if either exist
; (doesn't matter which), and the values differ.
; [40] Go to next node on each side (which we know exist).
; [50] Check if we have moved past the end of the subtree.
; [60] If either or both %1,%2 put us at end of subtree, return.
; [70] Find the first different subscript or both will be "".
; [80] If both final subscripts "", subscripts are the same so check
; values, and either return of loop.
; [90] Subscripts don't match, return determine order so we can return
; node that is missing.
; $$FDR($NAME(a),$NAME(b))
; Find first different nodes in two trees (or subtrees). Will
; work with locals or globals, except locals of the for %, %1,
; %2, %3, or %4. Returns a string containing the two references
; where the first difference separated by "'=". If a node is
; found in one tree that is not present in the other, the missing
; reference is replaced by a question mark ("?"). If both trees
; are the same, an empty string is returned.
;
FDR(%1,%2) ; [10]
NEW %3,%4,% ; [20]
SET %3=$DATA(@%1,%5)#10,%4=$DATA(@%2,%6)#10
QUIT:%3'=%4||(%3&&(%5'=%6)) $S(%3:%1,1:"?")_"'="_$S(%2:b,1:"?") ; [30]
SET (%3,%4)=""
lr SET %3=$ORDER(@%1@(%3)),%4=$ORDER(@%2@(%4)) Q:%3=""&&(%4="") "" ; [40]
IF %3=%4 SET %=$$FDR($NA(@%1@(%3)),$NA(@%2@(%4))) G:%="" lr Q % ; [50]
QUIT:%3]]%4 "?'="_$NAME(@%2@(%4)) QUIT $NAME(@%1@(%3))_"'=?" ; [60]
; ------------
; [10] %1,%2 Reference to nodes under test.
; [20] %3,%4 Upto [30] used for Do %1,%2 exist (respectively)?
; After [30] Subscripts of %1,%2.
; % Results of recursive call.
; [30] Return if the existence of %1 and %2 differ or if either exist
; (doesn't matter which), and the values differ.
; [40] Go to next subscript at this level.
; [50] If the subscripts are the same, check the sub-tree
; recursively. Loop or quit, depending upon finding a difference.
; [60] If subscripts differ, there is a missing node. Return the
; missing one.
- Log in to post comments