public IEnumerable <TEdit> CalculateEdit <TEdit>( ILevenstainMatrix matrix, IList <TSource> source, IList <TTarget> target, Func <TSource, TTarget, TEdit> editSelector, bool reverse = false) { var result = InternalCalculateEdit(matrix, source, target, editSelector); return(reverse ? result : result.Reverse()); //default is already reversed }
private IEnumerable <TEdit> InternalCalculateEdit <TEdit>( ILevenstainMatrix matrix, IList <TSource> source, IList <TTarget> target, Func <TSource, TTarget, TEdit> editSelector) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (target == null) { throw new ArgumentNullException(nameof(target)); } if (editSelector == null) { throw new ArgumentNullException(nameof(editSelector)); } if (matrix == null) { throw new ArgumentNullException(nameof(matrix)); } if (matrix.M != (source.Count + 1) || matrix.N != (target.Count + 1)) { throw new ArgumentOutOfRangeException("Invalid matrix size."); } if (Options == null) { throw new ArgumentNullException(nameof(Options)); } int i = matrix.M - 1; int j = matrix.N - 1; while (i != 0 || j != 0) { if (i == 0) { yield return(editSelector(default(TSource), target[j - 1])); j--; continue; } if (j == 0) { yield return(editSelector(source[i - 1], default(TTarget))); i--; continue; } var ss1 = source[i - 1]; var ss2 = target[j - 1]; var diag = matrix[i - 1, j - 1] + Options.GetUpdateCost(ss1, ss2); var left = matrix[i, j - 1] + Options.GetCreateCost(ss2); var up = matrix[i - 1, j] + Options.GetDeleteCost(ss1); if (diag <= left && diag <= up) { yield return(editSelector(ss1, ss2)); i--; j--; } else if (left <= diag && left <= up) { yield return(editSelector(default(TSource), ss2)); j--; } else if (up <= diag && up <= left) { yield return(editSelector(ss1, default(TTarget))); i--; } else { throw new InvalidOperationException(); } } }