Home About Contact
Kotlin

曖昧な処理のためにレーベンシュタイン距離を使う

レーベンシュタイン距離 という二つの文字列がどの程度異なっているかを示す距離の計算をするJavaのライブラリがあるので、それを使う。

環境

$ kotlinc -version
info: kotlinc-jvm 1.8.10 (JRE 17.0.9+9-Ubuntu-122.04)

使い方

Levenshtein のインスタンスを生成してメソッド distance に二つの比較したい文字列を渡すだけです。

import info.debatty.java.stringsimilarity.Levenshtein

val levenshtein = Levenshtein()
val d = levenshtein.distance("hoge", "hogehoge")
println(d)

調べたい文字列.distance(候補の文字列) のように使いたかったので、拡張関数を定義しました。

fun String.distance(that:String): Double {
    return Levenshtein().distance(this, that)
}

これで "hoge".distance("hogehoge") のように使うことができます。

通常、文字列のような基本的なクラスに拡張関数で勝手にメソッドを生やすのは悪手だと思いますが、 単なるテストスクリプトなので、よいことにします。

TYPO があっても許容する例

Caffe Americano が正式商品名だとして、 Caffe AmericanooCaffee Americanoo のように少し間違ったデータがあった場合に、 これらを 元の Caffe Americano と同一文字列として扱いたい、という場合。

コード全体。

distance.main.kts:

@file:Repository("https://repo1.maven.org/maven2/")
@file:DependsOn("info.debatty:java-string-similarity:2.0.0")

import info.debatty.java.stringsimilarity.Levenshtein

val name0 = "Caffe Americano"
val name1 = "Caffe Americanoo"
val name2 = "Caffee Americanoo"

fun String.distance(that:String): Double {
    return Levenshtein().distance(this, that)
}

println(name0.distance(name0)) // 0.0
println(name0.distance(name1)) // 1.0
println(name0.distance(name2)) // 2.0

実行する。

$ kotlinc -script distance.main.kts

レーベンシュタイン距離の値が大きいほど違いが大きい文字列同士ということになります。 完全に一致している場合は 0.0 になります。

これを使って たとえば、「レーベンシュタイン距離が 2.0 以内ならば同じ文字列と見なす」というようにして、曖昧な処理を行います。