/// <inheritdoc /> public override ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality, DMerge <T> merge) { // if there not equal, Union results in null if (!equality(this, other)) { return(null); } // Create a new node using the provided merge rule. // The merge rule determines how equal values resolve TreeNode <T> unionTree = new TreeNode <T>(merge(Value, other.Value)); // Get the children of the other node, to test against the children of the current node List <ITreeNode <T> > testNodes = new List <ITreeNode <T> >(other.Children); // Foreach node in Children, preform a test to determine the case and handle // the union calculation foreach (ITreeNode <T> child in Children) { // candidates for a deeper union are testsNodes that equal the child IEnumerable <ITreeNode <T> > candidates = testNodes.Where(n => equality(n, child)); // if no candidates, add this child to the new tree if (candidates == null || candidates.Count() == 0) { child.Copy(unionTree); continue; } // Determine which candidate should be used to perform the union // This is the most similar candidate ITreeNode <T> chosenCandidate = null; if (candidates.Count() == 1) { chosenCandidate = candidates.First(); } else { chosenCandidate = child.MostSimilar(candidates); } // Perform a union with the chosen candidate InternalAddChild(unionTree, child.Union(chosenCandidate, equality, merge) as TreeNode <T>); // Remove the candidate testNodes.Remove(chosenCandidate); } // Add all remaining nodes without performing a merge foreach (ITreeNode <T> node in testNodes) { node.Copy(unionTree); } return(unionTree); }
/// <inheritdoc /> public abstract ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality, DMerge <T> merge);
/// <inheritdoc /> public override ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality, DMerge <T> merge) { // if not equal, return null if (!equality(this, other)) { return(null); } // since values are equal, if they both have no children, return node with value if (ChildCount == 0 && other.ChildCount == 0) { return(new UniqueChildrenTreeNode <T>(merge(Value, other.Value))); } // return copy of node with children if only 1 has children if (ChildCount > 0 && other.ChildCount == 0) { return(Copy()); } if (other.ChildCount > 0 && ChildCount == 0) { return(other.Copy()); } // set up the union tree for recursive calculation UniqueChildrenTreeNode <T> unionTree = new UniqueChildrenTreeNode <T>(merge(Value, other.Value)); // sort out children in both that have no equivalent in other // perform a union on any nodes that match List <ITreeNode <T> > otherNodesNotInOriginal = new List <ITreeNode <T> >(other.Children); List <ITreeNode <T> > originalNodesNotInOther = new List <ITreeNode <T> >(); foreach (ITreeNode <T> child in Children) { ITreeNode <T> matchingOtherNode = otherNodesNotInOriginal.Find(n => equality(n, child)); if (matchingOtherNode == default(ITreeNode <T>)) { originalNodesNotInOther.Add(child); } else { UniqueChildrenTreeNode <T> newUnion = child.Union(matchingOtherNode) as UniqueChildrenTreeNode <T>; if (newUnion == null) { continue; } // add union of matching nodes to tree UnsafeAddChild(unionTree, newUnion); otherNodesNotInOriginal.Remove(matchingOtherNode); } } // copy other nodes missing from original foreach (ITreeNode <T> node in otherNodesNotInOriginal) { node.Copy(unionTree); } // copy original nodes missing from other foreach (ITreeNode <T> node in originalNodesNotInOther) { node.Copy(unionTree); } return(unionTree); }