Ruby

levenshtein gem で DroidKaigi と DanKogai の類似度を測定する #ruby #droidkaigi


概要

levenshtein gem DroidKaigi:sunglasses::white_circle: DanKogai類似度 を測定します


経緯

このあたりのツイートがことのはじめ。

自分も同時に、 「あー、 DanKogai に見えるな」 と思っていたので

DroidKaigi のツイートに参戦していた。

(ฅ・ω・)ฅ /{  ドロイド君にサスペンダーをつける職人さんまだー } DroidKaigi DanKogai

と呟いたら・・・

作っていただけた!

@rosylilly さん、ありがとうございます! :book:

ちなみに DanKogai さんご本人の目にも止まり、こんな結果になった模様


本題

levenshtein gem で DroidKaigiDanKogai の類似度を測定します。

levenshtein は レーベンシュタイン距離 で類似度を計測します。


サンプルコード1

require 'levenshtein'

require 'pp'

module Levenshtein
module_function
def call(main_word)
levenshtein =->(x, y) { Levenshtein.similarity(x, y) }
levenshtein.curry[main_word]
end

def similarity(one, other)
1 - Levenshtein.normalized_distance(one, other)
end
end

class Array
def sort_by_similarity_desc_word_asc
sort_by { |e|[-e[:similarity], e[:word]] }
end
end

module GestaltKogai
module_function
MAIN_WORD = 'DanKogai'
GESTALT_WORDS = %w(
DanKogai
DroidKaigi
DenKigai
DonKonishi
DensyaotoKo
DonkeyKong
DanNorth
DoxyGen
DoorKeeper
DaisuKi
DaiKirai
DaiKanYama
DanjyoKosai
DandanKokorohikareteku
DondoKodon
DamKaraoke
Horiemon
)

def similarities
kogai_levenshtein = Levenshtein.(MAIN_WORD)
GESTALT_WORDS.each_with_object([]) do |gestalt_word, memo|
memo << {
word: gestalt_word,
similarity: kogai_levenshtein.(gestalt_word)
}
end
end
end

results = GestaltKogai.similarities
pp results.sort_by_similarity_desc_word_asc


出力

[{:word=>"DanKogai", :similarity=>1.0},

{:word=>"DenKigai", :similarity=>0.75},
{:word=>"DanjyoKosai", :similarity=>0.6363636363636364},
{:word=>"DaiKirai", :similarity=>0.625},
{:word=>"DanNorth", :similarity=>0.5},
{:word=>"DonKonishi", :similarity=>0.5},
{:word=>"DaiKanYama", :similarity=>0.4},
{:word=>"DamKaraoke", :similarity=>0.4},
{:word=>"DondoKodon", :similarity=>0.4},
{:word=>"DaisuKi", :similarity=>0.375},
{:word=>"DonkeyKong", :similarity=>0.30000000000000004},
{:word=>"DroidKaigi", :similarity=>0.30000000000000004},
{:word=>"DandanKokorohikareteku", :similarity=>0.2727272727272727},
{:word=>"DensyaotoKo", :similarity=>0.2727272727272727},
{:word=>"DoorKeeper", :similarity=>0.19999999999999996},
{:word=>"DoxyGen", :similarity=>0.125},
{:word=>"Horiemon", :similarity=>0.0}]


おまけ

did_you_mean という gem というタイポ検出ツールがあって、

その中でもlevenshtein は レーベンシュタイン距離 で文字列のを用いて、類似度を測っています。

詳しくは下記エントリにまとめてあります。

Ruby | did_you_mean gem でスペルミスを検出+ did_you_mean gem のコードリーディング


:bow: お礼の広告コーナー

私の何気ない呟きに反応してドロイド君( DanKogai ver )を作ってくださった @rosylilly さんへの感謝の気持ちとして

@rosylilly さんの Qiita のエントリを 3 つほど紹介したいと思います。


:dog2: 本気で使う Docker

今を時めく、 :whale: Docker のエントリです。

はてなブックマーク内でも

知らなかった -> "quay.io"

よかった。本気で使ってる人いたんだ。

ふむふむ(´・ω・`)

めっちゃ良い

など、反響を呼んでいるエントリです。


:monkey: Ruby で作る、簡単 CLI ツールのススメ

Bundler + Thor を作った gem の作成から、

Private な環境で gem を配布する方法など

*社内で使う小さな便利 gem *に関わるノウハウが分かりやすくまとめてあります。


:bird: 複数人での Git 開発に便利な 3 つのコマンド

説明すると丸ごとネタバレになりそうなのでリンク先でお楽しみください。


:bow: 謝辞

最後になりましたが、 Dan Kogai さんに感謝いたします。

当記事を読んで、もし気を悪くされましたら削除させていただきます。


:link: 外部資料


:books: 脚注





  1. Ruby に不慣れな方は知らなそうなものをいっぱい使ってますが、このエントリの主題から外れるので特に解説はしません。気になったら次のキーワードでググってみてください [ruby curry], [ruby to_proc call], [module module_function], [ruby 配列 %記法]