Skip to content

Commit c94b78a

Browse files
committed
Levenshtein, programming style
The version before this commit was I believe correct. I would therefore totally understand if this pull request was rejected. However I think levenshtein provides a very nice example to demonstrate some of the functionality and pitfalls of coffeescript. First I am not too fond of the "return unless" statement. It feels a bit uncanny to find a non indented return in the middle of a function. Most important I am not fond of what this statement is trying to hide. In most languages, checking for the empty string is not useful.  see Discussion section.
1 parent 7437de8 commit c94b78a

File tree

1 file changed

+25
-18
lines changed

1 file changed

+25
-18
lines changed

chapters/strings/matching-strings.md

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,37 @@ Calculate the edit distance, or number of operations required to transform one s
1313

1414
{% highlight coffeescript %}
1515

16-
Levenshtein =
17-
(str1, str2) ->
18-
16+
levenshtein = (str1, str2) ->
17+
1918
l1 = str1.length
2019
l2 = str2.length
20+
prevDist = [0..l2]
21+
nextDist = [0..l2]
22+
23+
for i in [1..l1] by 1
24+
nextDist[0] = i
25+
for j in [1..l2] by 1
26+
if (str1.charAt i-1) == (str2.charAt j-1)
27+
nextDist[j] = prevDist[j-1]
28+
else
29+
nextDist[j] = 1 + Math.min prevDist[j], nextDist[j-1], prevDist[j-1]
30+
[prevDist,nextDist]=[nextDist, prevDist]
31+
32+
prevDist[l2]
2133

22-
return Math.max l1, l2 unless l1 and l2
34+
{% endhighlight %}
2335

24-
i = 0; j = 0; distance = []
36+
## Discussion
2537

26-
distance[i] = [i] for i in [0..l1]
27-
distance[0][j] = j for j in [0..l2]
38+
You can use either Hirschberg or Wagner–Fischer's algorithm to calculate a Levenshtein distance. This example uses Wagner–Fischer's algorithm.
2839

29-
for i in [1..l1]
30-
for j in [1..l2]
31-
distance[i][j] = Math.min distance[i - 1][j] + 1,
32-
distance[i][j - 1] + 1,
33-
distance[i - 1][j - 1] +
34-
if (str1.charAt i - 1) is (str2.charAt j - 1) then 0 else 1
40+
This version of Levenshtein algorithm is linear in memory, quadratic in time.
3541

36-
distance[l1][l2]
37-
38-
{% endhighlight %}
42+
str.charAt i is preferred here to str[i] because the latter syntax is not supported by some browsers (e.g. IE7).
3943

40-
## Discussion
44+
At first glance the use of "by 1" in the two loops might look useless. It is actually here to avoid a common danger
45+
of the coffeescript [i..j] syntax. If str1 or str2 is an empty string, then [1..l1] or [1..l2] will return [1,0].
46+
The loops with the "by 1" statement also compiles to cleaner / slightly more performant javascript.
4147

42-
You can use either Hirschberg or Wagner–Fischer's algorithm to calculate a Levenshtein distance. This example uses Wagner–Fischer's algorithm.
48+
Finally the optimization of recycling of arrays at the end of the loops is mainly here to
49+
demonstrate the syntax of coffeescript for swapping two variables.

0 commit comments

Comments
 (0)