문제

죄송합니다. 아직 FP를 얻지 못합니다. 단락 부문으로 빈 줄을 가정하면 파이썬으로 다음과 같이 할 수 있습니다.

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

Erlang 또는 Haskell에서 어떻게 하시겠습니까?

도움이 되었습니까?

해결책

나는 시작 Haskell 프로그래머 (그리고 내가 배운 작은 Haskell은 5 년 전) 일뿐입니다. 그러나 처음에는 Accumulator ( "현재 단락")가 지나가는 기능의 자연스러운 번역을 쓸 것입니다. (명확성을 위해 유형을 추가했습니다) :

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 Experience는 이와 같은 작업을 수행하기위한 거의 항상 도서관 기능이 있음을 시사합니다. :) 하나의 관련 기능이 호출됩니다. 그룹비, 그리고 거의 작동합니다.

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

죄송합니다. 우리가 정말로 필요한 것은 "분할"이며 라이브러리에 없습니다, 그러나 우리는 우리 자신을 스스로 필터링 할 수 있습니다.

paragraphs4 :: [Line] -> [Para]
paragraphs4 ls = map (filter (/= "")) (groupBy (\x y -> y /= "") ls)

또는 시원하기를 원한다면 논쟁을 없애고 무의미한 방법으로 할 수 있습니다.

paragraphs5 = map (filter (/= "")) . groupBy (\x y -> y /= "")

나는 더 짧은 방법이 있다고 확신합니다. :-)

편집하다: 일시적인 그것을 지적합니다 (not . null) 보다 깨끗합니다 (/= ""). 그래서 우리는 쓸 수 있습니다

paragraphs = map (filter $ not . null) . groupBy (const $ not . null)

반복 (not . null) 우리가 이것을 실제로 함수로 추상화해야한다는 강력한 표시이며, 이것이 바로 data.list.split 모듈 아래 답변에서 지적한대로.

다른 팁

나는 또한 Haskell을 배우려고 노력하고 있습니다. 이 질문에 대한 해결책은 다음과 같습니다.

paragraphs :: [String] -> [[String]]
paragraphs [] = []
paragraphs lines = p : (paragraphs rest)
    where (p, rest) = span (/= "") (dropWhile (== "") lines)

내가 기능을 사용하는 곳 데이터. 목록. 내가 사용하는 것들은 이미 Prelude에서 사용할 수 있지만 링크에서 해당 문서를 찾을 수 있습니다.

아이디어는 첫 번째 단락을 사용하는 것입니다 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 좋은 후보 인 것 같습니다. 사용자 정의 기능을 사용하여 어떤 줄이 "동일"인지 결정하므로 동일한 단락 "동일"으로 선을 만드는 것을 제공 할 수 있습니다. 예를 들어:

import Data.List( groupBy )

inpara :: String -> String -> Bool
inpara _ "" = False
inpara _ _  = True

paragraphs :: [String] -> [[String]]
paragraphs = groupBy inpara

이것은 그 이후로 몇 가지 한계가 있습니다 inpara 인접한 두 개의 라인 만 비교할 수 있으며 더 복잡한 논리는 다음과 같은 프레임 워크에 맞지 않습니다. 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"]]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top