質問
申し訳ありませんが、私はかなりまだFPを得ることはありません、私は段落部門として空行を想定し、ラインの配列の配列に行のシーケンスを分割したい、私はこのようなPythonでそれを行うことができます:
def get_paraghraps(lines):
paragraphs = []
paragraph = []
for line in lines:
if line == "": # I know it could also be "if line:"
paragraphs.append(paragraph)
paragraph = []
else:
paragraph.append(line)
return paragraphs
あなたはアーランやHaskellでそれをやって行くだろうか?
解決
私はほんの始まりHaskellのプログラマ(と私が学んだ少しHaskellは5年前だった)んだけど、スタートのために、私はアキュムレータ(「現在の段落」)で、あなたの関数の自然な翻訳を記述します。 (私はわかりやすくするために、種類を追加しました)の周りに渡されます:
type Line = String
type Para = [Line]
-- Takes a list of lines, and returns a list of paragraphs
paragraphs :: [Line] -> [Para]
paragraphs ls = paragraphs2 ls []
-- Helper function: takes a list of lines, and the "current paragraph"
paragraphs2 :: [Line] -> Para -> [Para]
paragraphs2 [] para = [para]
paragraphs2 ("":ls) para = para : (paragraphs2 ls [])
paragraphs2 (l:ls) para = paragraphs2 ls (para++[l])
この作品ます:
*Main> paragraphs ["Line 1", "Line 2", "", "Line 3", "Line 4"]
[["Line 1","Line 2"],["Line 3","Line 4"]]
<時間>
だから、ソリューションです。しかし、その後、Haskellの経験は<のhref =「http://www.zvon.org/other/haskell/Outputlist/groupBy_f.html」と呼ばれるこの:)一つの関連機能のようなものを行うためのライブラリ関数は、ほとんど常に存在していることを示唆していますrel = "nofollowをnoreferrer"> GROUPBY を、そしてそれはほとんど機能します:
paragraphs3 :: [Line] -> [Para]
paragraphs3 ls = groupBy (\x y -> y /= "") ls
*Main> paragraphs3 ["Line 1", "Line 2", "", "Line 3", "Line 4"]
[["Line 1","Line 2"],["","Line 3","Line 4"]]
おっと。私たちが本当に必要なのは「splitBy」で、それが図書館にないのしかし、我々は悪いものを除外することができます自分ます:
paragraphs4 :: [Line] -> [Para]
paragraphs4 ls = map (filter (/= "")) (groupBy (\x y -> y /= "") ls)
または、あなたがクールになりたい場合は、あなたが引数を取り除くと、それを無意味な方法を行うことができます:
paragraphs5 = map (filter (/= "")) . groupBy (\x y -> y /= "")
私も短い方法があることを確認しています。 :-)
編集: ephemient には(not . null)
が(/= "")
よりもクリーンであることを指摘しています。だから私たちは書くことができます。
paragraphs = map (filter $ not . null) . groupBy (const $ not . null)
繰り返し(not . null)
は、私たちが本当に機能にアウトこの抽象べき強力な指標であり、これはどのような<のhref =「http://byorgey.wordpress.com/2008/12/21/datalistsplit/」でありますrel = "nofollowをnoreferrer">以下の回答で指摘したように、いのData.List.Splitモジュールます。
他のヒント
私はまた、Haskellのを学ぶためにしようとしています。この質問のための解決策が考えられます:
paragraphs :: [String] -> [[String]]
paragraphs [] = []
paragraphs lines = p : (paragraphs rest)
where (p, rest) = span (/= "") (dropWhile (== "") lines)
私はデータから関数を使用しているところ.LISTする。私が使用しているものは、すでにプレリュードから入手できますが、あなたは、リンクでのドキュメントを見つけることができます。
アイデアはspan (/= "")
を使用して最初の段落を見つけることです。これは、段落を返し、行は次のよう。私たちは、その後、私はrest
を呼び出す行の小さなリストに再帰ます。
最初の段落を分割する前に、我々はdropWhile (== "")
を使用して、任意の空行をドロップします。これは、段落を分離する空行(複数可)を食べることが重要です。
paragraphs :: [String] -> [[String]]
paragraphs [] = []
paragraphs lines = p : (paragraphs $ tail rest)
where (p, rest) = span (/= "") lines
私たちは最後の段落に達したときrest
が空の文字列であるので、これは失敗します:
*Main> paragraphs ["foo", "bar", "", "hehe", "", "bla", "bla"] [["foo","bar"],["hehe"],["bla","bla"]*** Exception: Prelude.tail: empty list
空行を削除すると、これを解決し、そしてそれはまた、コードは、私はユーザーとして期待するものである、段落の区切りとして、空行の任意の数の治療になります。
きれいな解決策は、分割から適切なものを使用することです>パッケージます。
あなたが最初にそれをインストールする必要がありますが、その後Data.List.Split.splitWhen null
は完全に仕事をする必要があります。
再帰的に考えてみます。
get_paragraphs [] paras para = paras ++ [para]
get_paragraphs ("":ls) paras para = get_paragraphs ls (paras ++ [para]) []
get_paragraphs (l:ls) paras para = get_paragraphs ls paras (para ++ [l])
あなたはグループに行をしたいので、groupBy
からData.List
は良い候補のように思えます。これは、1つは、同じ段落内の行は「等しい」を作る何かを供給することができるように「同じ」である行を決定するためにカスタム関数を使用しています。たとえばます:
import Data.List( groupBy )
inpara :: String -> String -> Bool
inpara _ "" = False
inpara _ _ = True
paragraphs :: [String] -> [[String]]
paragraphs = groupBy inpara
inpara
は2つのだけの隣接する行を比較することができますので、これは、いくつかの制限があり、より複雑なロジックはgroupBy
によって与えられた枠組みに収まりません。より柔軟であれば、より元素ソリューション。基本的な再帰のいずれかを使用して書くことができます:
paragraphs [] = []
paragraphs as = para : paragraphs (dropWhile null reminder)
where (para, reminder) = span (not . null) as
-- splits list at the first empty line
span
が供給関数が偽(最初の空行)となるポイントでリストを分割し、dropWhile
が供給関数が真(先頭の空行)であるための主要な要素を削除します。
ないより遅れてます。
import Data.List.Split (splitOn)
paragraphs :: String -> [[String]]
paragraphs s = filter (not . null) $ map words $ splitOn "\n\n" s
paragraphs "a\nb\n\nc\nd" == [["a", "b"], ["c", "d"]]
paragraphs "\n\na\nb\n\n\nc\nd\n\n\n" == [["a", "b"], ["c", "d"]]
paragraphs "\n\na\nb\n\n \n c\nd\n\n\n" == [["a", "b"], ["c", "d"]]