3

私はHaskellを初めて使用し、現在、文字列の解析が必要な問題を解決しようとしています。入力文字列には、引用符で囲まれた単語のコンマ区切りリストが含まれています。この単一の文字列を文字列として単語のリストに解析したいと思います。そのような文字列の解析についてどこから始めればよいですか?役立つpartuclarモジュールや関数はありますか?

ps完全な解決策を投稿しないでください。出発点へのポインタを求めているので、その方法を学ぶことができます。

4

6 に答える 6

6

最も強力なソリューションは、パーサーコンビネーターです。Haskellにはこれらのいくつかがありますが、私の頭に浮かぶ最も重要なものは次のとおりです。

  • parsec:非常に優れた汎用解析ライブラリ
  • attoparsec:parsecのより高速なバージョンであり、エラーメッセージの品質とその他の機能を犠牲にして速度を向上させます
  • uu-parsinglib:非常に強力な解析ライブラリ

doパーサーコンビネーターの大きな利点は、表記法(または必要Applicativeに応じてスタイル)を使用してパーサーを定義するのが非常に簡単なことです。

すばやく簡単な文字列操作機能が必要な場合は、文字列を操作するために必要な機能を提供するtextライブラリ(高性能のバイトエンコード文字列の場合)またはData.List(通常のリストエンコード文字列の場合)を参照してください。

于 2012-06-26T15:56:25.383 に答える
6

これは非常に単純な状況であるため、最終的に自分の解析関数をロールすることにしました。この質問を最初に投稿して以来、Haskellについて多くのことを学びました。ここで、解決策を文書化したいと思います。

split :: Char -> String -> [String]
split _ "" = []
split c s = firstWord : (split c rest)
    where firstWord = takeWhile (/=c) s
          rest = drop (length firstWord + 1) s

removeChar :: Char -> String -> String
removeChar _ [] = []
removeChar ch (c:cs)
    | c == ch   = removeChar ch cs
    | otherwise = c:(removeChar ch cs)

main = do
    handle <- openFile "input/names.txt" ReadMode
    contents <- hGetContents handle
    let names = sort (map (removeChar '"') (split ',' contents))
    print names
    hClose handle
于 2012-07-31T18:28:20.473 に答える
5

sはHaskellStringのsの単なるリストであるため、 Data.Listは(Haskellを学習するために)探し始めるのに適した場所です。Char

より複雑な場合(たとえば、コンマが引用符の中にネストされている可能性があり、無視する必要がある場合)、parsec(Danielが述べたように)がより良い解決策になります。

また、CSVの解析を検討している場合は、Text.CSVを試すことができますが私は試していません。そのため、これがどれほど役立つかはわかりません。

于 2012-06-26T03:21:09.033 に答える
3

先に進むための特に生意気な方法は次のとおりです。

parseCommaSepQuotedWords :: String -> [String]
parseCommaSepQuotedWords s = read ("[" ++ s ++ "]")

これはうまくいくかもしれませんが、それは非常に壊れやすく、かなりばかげています。基本的に、文字列のリストを書くHaskellの方法があなたの方法とほぼ一致するという事実を使用しているので、組み込みのReadインスタンスはほとんどあなたが望むものです。より良いエラー報告のために使用することもできますreadsが、実際には、おそらく完全に別のことをしたいと思うでしょう。

一般的に、一見の価値があります-それは使うのが楽しいことであり、もともと私がHaskellparsec本当に興奮したことの1つです。しかし、自家製のソリューションが必要な場合は、とcaseの結果に関するステートメントを使用して簡単なことを書くことがよくspanありbreakます。入力で次のセミコロンを探しているとします。次に、break (== ';') inpを返します(before, after)。ここで、

  • beforeinp最初のセミコロン(またはセミコロンがない場合はすべて)までの内容です(含まれていません)。
  • after文字列の残りの部分です:
    • 空でない場合after、最初の要素はセミコロンです
    • 他に何が起こっても、before ++ after == inp

したがって、セミコロンで区切られたステートメントのリストを解析するには、次のようにします。

parseStmts :: String -> Maybe [Stmt]
parseStmts inp = case break (== ';') inp of
  (before, _ : after) -> -- ...
    -- ^ before is the first statement
    --     ^ ignore the semicolon
    --           ^ after is the rest of the string
  (_, []) -> -- inp doesn't contain any semicolons
于 2012-06-26T13:30:18.157 に答える
1

この質問に遭遇した人に完全な答えを与えるために、Data.Textにはいくつかの優れた機能もあります。

于 2012-06-26T05:53:58.130 に答える
1

「実際の仕事」であるものにはパーセクを使用してください。

紹介については、https://therning.org/magnus/archives/tag/parsecをお読みください

于 2012-06-26T07:41:51.940 に答える