-
Notifications
You must be signed in to change notification settings - Fork 124
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve typo correction suggestions (#150)
- Loading branch information
Showing
15 changed files
with
263 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
clikt/src/commonMain/kotlin/com/github/ajalt/clikt/core/JaroWinkerSimilarity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.github.ajalt.clikt.core | ||
|
||
import kotlin.math.max | ||
import kotlin.math.min | ||
|
||
|
||
private fun jaroSimilarity(s1: String, s2: String): Double { | ||
if (s1.isEmpty() && s2.isEmpty()) return 1.0 | ||
else if (s1.isEmpty() || s2.isEmpty()) return 0.0 | ||
else if (s1.length == 1 && s2.length == 1) return if (s1[0] == s2[0]) 1.0 else 0.0 | ||
|
||
val searchRange: Int = max(s1.length, s2.length) / 2 - 1 | ||
val s2Consumed = BooleanArray(s2.length) | ||
var matches = 0.0 | ||
var transpositions = 0 | ||
var s2MatchIndex = 0 | ||
|
||
for ((i, c1) in s1.withIndex()) { | ||
val start = max(0, i - searchRange) | ||
val end = min(s2.lastIndex, i + searchRange) | ||
for (j in start..end) { | ||
val c2 = s2[j] | ||
if (c1 != c2 || s2Consumed[j]) continue | ||
s2Consumed[j] = true | ||
matches += 1 | ||
if (j < s2MatchIndex) transpositions += 1 | ||
s2MatchIndex = j | ||
break | ||
} | ||
} | ||
|
||
return when (matches) { | ||
0.0 -> 0.0 | ||
else -> (matches / s1.length + | ||
matches / s2.length + | ||
(matches - transpositions) / matches) / 3.0 | ||
} | ||
} | ||
|
||
internal fun jaroWinklerSimilarity(s1: String, s2: String): Double { | ||
// Unlike classic Jaro-Winkler, we don't set a limit on the prefix length | ||
val prefixLength = s1.commonPrefixWith(s2).length | ||
val jaro = jaroSimilarity(s1, s2) | ||
val winkler = jaro + (0.1 * prefixLength * (1 - jaro)) | ||
return min(winkler, 1.0) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
clikt/src/commonTest/kotlin/com/github/ajalt/clikt/core/JaroWinkerSimilarityTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.github.ajalt.clikt.core | ||
|
||
import io.kotest.data.forall | ||
import io.kotest.matchers.doubles.plusOrMinus | ||
import io.kotest.matchers.shouldBe | ||
import io.kotest.tables.row | ||
import kotlin.test.Test | ||
|
||
|
||
class JaroWinkerSimilarityTest { | ||
@Test | ||
fun jaroWinklerSimilarity() = forall( | ||
row("", "", 1.0), | ||
row("", "a", 0.0), | ||
row("a", "", 0.0), | ||
row("a", "a", 1.0), | ||
row("aa", "aa", 1.0), | ||
row("aaapppp", "", 0.0), | ||
row("fly", "ant", 0.0), | ||
row("cheeseburger", "cheese fries", 0.91), | ||
row("frog", "fog", 0.93), | ||
row("elephant", "hippo", 0.44), | ||
row("hippo", "elephant", 0.44), | ||
row("hippo", "zzzzzzzz", 0.0), | ||
row("hello", "hallo", 0.88) | ||
) { s1, s2, expected -> | ||
jaroWinklerSimilarity(s1, s2) shouldBe (expected plusOrMinus 0.01) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
clikt/src/commonTest/kotlin/io/kotest/matchers/doubles/Tolerance.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
Copyright 2016 sksamuel | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
package io.kotest.matchers.doubles | ||
|
||
import io.kotest.matchers.Matcher | ||
import io.kotest.matchers.MatcherResult | ||
import kotlin.math.abs | ||
|
||
/** | ||
* Creates a matcher for the interval [[this] - [tolerance] , [this] + [tolerance]] | ||
* | ||
* | ||
* ``` | ||
* 0.1 shouldBe (0.4 plusOrMinus 0.5) // Assertion passes | ||
* 0.1 shouldBe (0.4 plusOrMinus 0.2) // Assertion fails | ||
* ``` | ||
*/ | ||
infix fun Double.plusOrMinus(tolerance: Double): ToleranceMatcher = ToleranceMatcher( | ||
this, | ||
tolerance) | ||
|
||
class ToleranceMatcher(private val expected: Double?, private val tolerance: Double) : Matcher<Double?> { | ||
override fun test(value: Double?): MatcherResult { | ||
return if(value == null || expected == null) { | ||
MatcherResult(value == expected, "$value should be equal to $expected", "$value should not be equal to $expected") | ||
} else if (expected.isNaN() && value.isNaN()) { | ||
println("[WARN] By design, Double.Nan != Double.Nan; see https://stackoverflow.com/questions/8819738/why-does-double-nan-double-nan-return-false/8819776#8819776") | ||
MatcherResult(false, | ||
"By design, Double.Nan != Double.Nan; see https://stackoverflow.com/questions/8819738/why-does-double-nan-double-nan-return-false/8819776#8819776", | ||
"By design, Double.Nan != Double.Nan; see https://stackoverflow.com/questions/8819738/why-does-double-nan-double-nan-return-false/8819776#8819776" | ||
) | ||
} else { | ||
if (tolerance == 0.0) | ||
println("[WARN] When comparing doubles consider using tolerance, eg: a shouldBe (b plusOrMinus c)") | ||
val diff = abs(value - expected) | ||
MatcherResult(diff <= tolerance, "$value should be equal to $expected", "$value should not be equal to $expected") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.