web-dev-qa-db-ja.com

「stringcontainsX」メソッドを書くためのより良い方法はありますか?

Haskellを使って見つめただけで、(私が知る限り)文字列をチェックして小さな文字列が含まれているかどうかを直接確認する方法がないことに気づきました。だから私はそれを撃つだけだと思いました。

基本的に、2つの文字列が同じサイズで、等しいかどうかを確認するというアイデアでした。チェック対象の文字列が長かった場合は、再帰的に頭を下げて、チェック対象の文字列が同じ長さになるまでチェックを再実行してください。

残りの可能性は、パターンマッチングを使用して処理しました。これは私が思いついたものです:

stringExists "" wordToCheckAgainst = False
stringExists wordToCheckFor "" = False
stringExists wordToCheckFor wordToCheckAgainst | length wordToCheckAgainst < length wordToCheckFor = False
                                               | length wordToCheckAgainst == length wordToCheckFor = wordToCheckAgainst == wordToCheckFor
                                               | take (length wordToCheckFor) wordToCheckAgainst == wordToCheckFor = True
                                               | otherwise = stringExists wordToCheckFor (tail wordToCheckAgainst)
21
Programmin Tool

検索した場合 Hoogle 探している関数のシグネチャを検索します(String -> String -> Bool)上位の結果の中に isInfixOf が表示されるはずです。

47
Tom Crockett

isInfixOf from Data.Listは確かに問題を解決しますが、干し草の山や逆針が長い場合は、より高度な 文字列照合アルゴリズム を検討する必要があります。平均と最悪の場合の複雑さははるかに優れています。


¹aと、最初にたくさんのaがあり、最後に1つのbがある針だけで構成される非常に長い文字列について考えてみます。

24
Jan

テキスト処理のニーズに text packagetext on Hackage、現在はHaskell Platformの一部)を使用することを検討してください。 Unicodeテキストタイプを提供します。これは、組み込みのリストベースのStringよりも時間とスペースの効率が高くなります。文字列検索の場合、textパッケージ implements a Boyer-Mooreベースのアルゴリズム 。これは、Data.List.isInfixOfで使用される単純な方法よりも複雑です。 。

使用例:

Prelude> :s -XOverloadedStrings
Prelude> import qualified Data.Text as T
Prelude Data.Text> T.breakOnAll "abc" "defabcged"
[("def","abcged")]
Prelude Data.Text> T.isInfixOf "abc" "defabcged"
True
10