概要
levenshtein gem で DroidKaigi と DanKogai の 類似度 を測定します
経緯
このあたりのツイートがことのはじめ。
「DanKogai やります」かと思ったら DroidKaigi の空見だった件
— mattn (@mattn_jp) 2015, 2月 3
自分も同時に、 「あー、 DanKogai に見えるな」 と思っていたので
DroidKaigi のツイートに参戦していた。
(ฅ・ω・)ฅ /{ ドロイド君にサスペンダーをつける職人さんまだー } DroidKaigi DanKogai
と呟いたら・・・
@tbpgr 遅くなってすみません。ご査収ください。 pic.twitter.com/ag3Vve9rCP
— ハト (@rosylilly) 2015, 2月 3
作っていただけた!
@rosylilly さん、ありがとうございます!
ちなみに DanKogai さんご本人の目にも止まり、こんな結果になった模様。
アイコンこれにしたろか… <@rosylilly: DanKogai 、すごく楽しみなイベントになった pic.twitter.com/aW1f4ZyzeC
— Dan Kogai (@dankogai) 2015, 2月 3
本題
levenshtein gem で DroidKaigi
と DanKogai
の類似度を測定します。
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 のコードリーディング
お礼の広告コーナー
私の何気ない呟きに反応してドロイド君( DanKogai ver )を作ってくださった @rosylilly さんへの感謝の気持ちとして
@rosylilly さんの Qiita のエントリを 3 つほど紹介したいと思います。
本気で使う Docker
今を時めく、 Docker のエントリです。
はてなブックマーク内でも
知らなかった -> "quay.io"
よかった。本気で使ってる人いたんだ。
ふむふむ(´・ω・`)
めっちゃ良い
など、反響を呼んでいるエントリです。
Ruby で作る、簡単 CLI ツールのススメ
Bundler + Thor を作った gem の作成から、
Private な環境で gem を配布する方法など
**社内で使う小さな便利 gem **に関わるノウハウが分かりやすくまとめてあります。
複数人での Git 開発に便利な 3 つのコマンド
説明すると丸ごとネタバレになりそうなのでリンク先でお楽しみください。
謝辞
最後になりましたが、 Dan Kogai さんに感謝いたします。
当記事を読んで、もし気を悪くされましたら削除させていただきます。
外部資料
脚注
-
Ruby に不慣れな方は知らなそうなものをいっぱい使ってますが、このエントリの主題から外れるので特に解説はしません。気になったら次のキーワードでググってみてください
[ruby curry], [ruby to_proc call], [module module_function], [ruby 配列 %記法]
↩