public AlignmentNode(DiffOperation operation, double similarity, int nodeCount, [CanBeNull] AlignmentNode next) { Operation = operation; Similarity = similarity; NodeCount = nodeCount; Next = next; }
private AlignmentNode CalculateBestAlignment([NotNull] Dictionary <AlignmentKey, AlignmentNode> nodes, [NotNull] IList <T> collection1, int lower1, int upper1, [NotNull] IList <T> collection2, int lower2, int upper2) { var key = new AlignmentKey(lower1, lower2); AlignmentNode result; if (nodes.TryGetValue(key, out result)) { Assume.That(result != null); return(result); } if (lower1 == upper1 && lower2 == upper2) { result = new AlignmentNode(DiffOperation.Match, 0.0, 0, null); } else if (lower1 == upper1) { var restAfterInsert = CalculateBestAlignment(nodes, collection1, lower1, upper1, collection2, lower2 + 1, upper2); result = new AlignmentNode(DiffOperation.Insert, restAfterInsert.Similarity, restAfterInsert.NodeCount + 1, restAfterInsert); } else if (lower2 == upper2) { var restAfterDelete = CalculateBestAlignment(nodes, collection1, lower1 + 1, upper1, collection2, lower2, upper2); result = new AlignmentNode(DiffOperation.Delete, restAfterDelete.Similarity, restAfterDelete.NodeCount + 1, restAfterDelete); } else { // Calculate how the results will be if we insert a new element var restAfterInsert = CalculateBestAlignment(nodes, collection1, lower1, upper1, collection2, lower2 + 1, upper2); var resultInsert = new AlignmentNode(DiffOperation.Insert, restAfterInsert.Similarity, restAfterInsert.NodeCount + 1, restAfterInsert); // Calculate how the results will be if we delete an element var restAfterDelete = CalculateBestAlignment(nodes, collection1, lower1 + 1, upper1, collection2, lower2, upper2); var resultDelete = new AlignmentNode(DiffOperation.Delete, restAfterDelete.Similarity, restAfterDelete.NodeCount + 1, restAfterDelete); // Calculate how the results will be if we replace or modify an element var restAfterChange = CalculateBestAlignment(nodes, collection1, lower1 + 1, upper1, collection2, lower2 + 1, upper2); double similarity = _SimilarityFunc(collection1[lower1], collection2[lower2]); AlignmentNode resultChange = null; if (similarity >= _ModificationThreshold) { resultChange = new AlignmentNode(DiffOperation.Modify, similarity + restAfterInsert.Similarity, restAfterChange.NodeCount + 1, restAfterChange); } // Then pick the operation that resulted in the best average similarity result = resultDelete; if (resultInsert.AverageSimilarity > result.AverageSimilarity) { result = resultInsert; } if (resultChange?.AverageSimilarity > result.AverageSimilarity) { result = resultChange; } } nodes[key] = result; return(result); }