質問

申し訳ありませんが、私はかなりまだ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

空行を削除すると、これを解決し、そしてそれはまた、コードは、私はユーザーとして期待するものである、段落の区切りとして、空行の任意の数の治療になります。

再帰的に考えてみます。

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"]]
scroll top