大文字と小文字を区別しないで、辞書の単語を一致させようとしています。私の初期のアプローチ は次のようになります:大きい辞書の単語セットの大文字と小文字の変換
- read dict;すべての単語を小文字に変換し、セットに格納します。
- セット
のメンバーシップのチェック新しい単語はこれを達成するためのより良い(より効率的な)方法はありますか?私はハスケルにとって初めてです。
大文字と小文字を区別しないで、辞書の単語を一致させようとしています。私の初期のアプローチ は次のようになります:大きい辞書の単語セットの大文字と小文字の変換
のメンバーシップのチェック新しい単語はこれを達成するためのより良い(より効率的な)方法はありますか?私はハスケルにとって初めてです。
私はちょうどText
と一緒に、Stringsに変換するのではなく、代わりに使用します。
Data.Text.IO
は、ファイルからテキストを読み取るためhGetContents
、readFile
などのバージョンが含まれており、Data.Text
は、テキストのためのlines
を持っています。 T.tolower
とT.lines
を使用することにより
{-# LANGUAGE OverloadedStrings #-}
import System.IO
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Data.Set as S
main = do
let path = "/usr/share/dict/american-english"
h <- openFile path ReadMode
hSetEncoding h utf8
contents <- T.hGetContents h
let mySet = (S.fromList . map T.toLower . T.lines) contents
putStrLn $ show $ S.member "acadia" mySet
我々は、明示的なパック/アンパック呼び出しを避けます。
mySet
は、StringsではなくText値のセットになりました。 を使用すると、OverloadedStringsプラグマのリテラル"acadia"
は、テキスト値として と解釈されます。
はい、あなたが提案するものは妥当です。メインの質問にほとんど関係のないいくつかのいくつかの発言は、:
Text
なくString
使用してあなたの自己を制限する方が効率的でしょう。toCaseFold
の機能をtoLower
に設定することをお勧めします。この場合は、より適切です。あなたは私の最初の答えが役に立ったと評価していますが、
は私は単に単一延ByteStringとして全体の辞書を読み込み、単語を調べるために書いて尻込みソルバが実行...私は別のアプローチを提案してみましょうByteStringのバイナリ検索。
辞書は既にソートされていて、小文字に正規化されていなければなりませんが、辞書は静的であり、事前にわかっているので問題ありません。
もちろん、バイナリ検索を実行するときに(lo+hi)/2
を計算すると、単語の真ん中に位置する可能性があるので、現在の単語の先頭にバックアップするだけです。
この主な利点は、辞書の読み込みが非常に高速でメモリ効率が良いことです。さらに、検索アルゴリズムは良好なメモリ局所性を有する。私はそれを測定していませんが、Data.Set
を作成すると生データのサイズを2倍以上にすると驚くことはありません。
コードはここにあります:https://github.com/erantapaa/hoggle
このアプローチはうまくいくようです。おそらく、文字列の場合、ハッキングのどこかに最適化されたトライパッケージがありますが、これは既に良いです。 – chi