public int LevenshteinDistance <T>(T[] strOld, T[] strNew, IEqualityComparer <T> comparer = null, Func <Choice <T>, int> weight = null, bool allowTransposition = false) { var m1 = strOld.Length + 1; var m2 = strNew.Length + 1; if (comparer == null) { comparer = EqualityComparer <T> .Default; } if (weight == null) { weight = c => 1; } _ResizeArray(m1, m2); _num[0, 0] = 0; for (var i = 1; i < m1; i++) { _num[i, 0] = _num[i - 1, 0] + weight(Choice <T> .Remove(strOld[i - 1])); } for (var j = 1; j < m2; j++) { _num[0, j] = _num[0, j - 1] + weight(Choice <T> .Add(strNew[j - 1])); } for (var i = 1; i < m1; i++) { for (var j = 1; j < m2; j++) { if (comparer.Equals(strOld[i - 1], strNew[j - 1])) { _num[i, j] = _num[i - 1, j - 1]; } else { _num[i, j] = Math.Min(Math .Min( _num[i - 1, j] + weight(Choice <T> .Remove(strOld[i - 1])), _num[i, j - 1] + weight(Choice <T> .Add(strNew[j - 1])) ), _num[i - 1, j - 1] + weight(Choice <T> .Substitute(strOld[i - 1], strNew[j - 1])) ); if (allowTransposition && i > 1 && j > 1 && comparer.Equals(strOld[i - 1], strNew[j - 2]) && comparer.Equals(strOld[i - 2], strNew[j - 1])) { _num[i, j] = Math.Min(_num[i, j], _num[i - 2, j - 2] + weight(Choice <T> .Transpose(strOld[i - 1], strOld[i - 2]))); } } } } return(_num[m1 - 1, m2 - 1]); }
public List <Choice <T> > LevenshteinChoices <T>(T[] strOld, T[] strNew, IEqualityComparer <T> comparer = null, Func <Choice <T>, int> weight = null) { if (comparer == null) { comparer = EqualityComparer <T> .Default; } if (weight == null) { weight = c => 1; } LevenshteinDistance(strOld, strNew, comparer, weight); var i = strOld.Length; var j = strNew.Length; var result = new List <Choice <T> >(); while (i > 0 && j > 0) { if (comparer.Equals(strOld[i - 1], strNew[j - 1])) { result.Add(Choice <T> .Equal(strOld[i - 1])); i = i - 1; j = j - 1; } else { var cRemove = Choice <T> .Remove(strOld[i - 1]); var cAdd = Choice <T> .Add(strNew[j - 1]); var cSubstitute = Choice <T> .Substitute(strOld[i - 1], strNew[j - 1]); var remove = _num[i - 1, j] + weight(cRemove); var add = _num[i, j - 1] + weight(cAdd); var substitute = _num[i - 1, j - 1] + weight(cSubstitute); var min = Math.Min(remove, Math.Min(add, substitute)); if (substitute == min) { result.Add(cSubstitute); i = i - 1; j = j - 1; } else if (remove == min) { result.Add(cRemove); i = i - 1; } else if (add == min) { result.Add(cAdd); j = j - 1; } } } while (i > 0) { result.Add(Choice <T> .Remove(strOld[i - 1])); i = i - 1; } while (j > 0) { result.Add(Choice <T> .Add(strNew[j - 1])); j = j - 1; } result.Reverse(); return(result); }