Refactored, added unit tests and removed opIndex.

Moved checks for which Range is longer to levenshteinDistance() method.

Reverted to implementation found in original distance() with regards to
using front/popFront instead of opIndex.

Fixed formatting of return statement.

Added two unit tests for levenshteinDistance().

Credit to @Poita.
This commit is contained in:
James Carr 2014-05-26 00:32:39 +01:00
parent a9ae1023a2
commit 0d0a2c0308

View file

@ -7603,28 +7603,25 @@ struct Levenshtein(Range, alias equals, CostType = size_t)
CostType distance(Range s, Range t)
{
if (s.length > t.length)
{
auto swap = s.idup;
s = t;
t = swap;
}
auto slen = walkLength(s.save), tlen = walkLength(t.save);
CostType lastdiag, olddiag;
AllocMatrix(slen + 1,1);
AllocMatrix(slen + 1, 1);
foreach (y; 1 .. slen + 1)
{
matrix(y,0) = y;
}
foreach (x; 1 .. tlen + 1)
{
auto tfront = t.front;
t.popFront();
auto ss = s;
matrix(0,0) = x;
lastdiag = x - 1;
foreach (y; 1 .. rows)
{
olddiag = matrix(0,y);
auto cSub = lastdiag + (equals(s[y-1], t[x-1]) ? 0 : _substitutionIncrement);
auto cSub = lastdiag + (equals(ss.front, tfront) ? 0 : _substitutionIncrement);
ss.popFront();
auto cIns = matrix(0,y - 1) + _insertionIncrement;
auto cDel = matrix(0,y) + _deletionIncrement;
switch (min_index(cSub, cIns, cDel))
@ -7642,7 +7639,7 @@ struct Levenshtein(Range, alias equals, CostType = size_t)
lastdiag = olddiag;
}
}
return(matrix(0,slen));
return matrix(0,slen);
}
EditOp[] path(Range s, Range t)
@ -7771,7 +7768,14 @@ size_t levenshteinDistance(alias equals = "a == b", Range1, Range2)
if (isForwardRange!(Range1) && isForwardRange!(Range2))
{
Levenshtein!(Range1, binaryFun!(equals), size_t) lev;
return lev.distance(s, t);
if (walkLength(s.save) > walkLength(t.save))
{
return lev.distance(s, t);
}
else
{
return lev.distance(t, s);
}
}
///
@ -7784,6 +7788,8 @@ unittest
assert(levenshteinDistance("kitten", "sitting") == 3);
assert(levenshteinDistance!((a, b) => std.uni.toUpper(a) == std.uni.toUpper(b))
("parks", "SPARK") == 2);
assert(levenshteinDistance("parks".filter!"true", "spark".filter!"true") == 2);
assert(levenshteinDistance("ID", "I♥D") == 1);
}
/**