2017-11-11 2 views
3

테스트 준비를 위해 하스켈에서 과제를 진행 중입니다. 현재 작업은 다음 수식 뒤에 문자열을 토큰 화하도록 요청합니다. "tokenize str separate remove"를 실행하면 문자열 목록을 출력해야합니다. 문자열 "separate"에 나타나는 "str"의 모든 문자는 한 문자의 문자열이어야합니다. 문자열 "remove"에 나타나는 "str"의 모든 문자는 제거해야합니다. 분리형 또는 제거 형으로 나타나지 않는 문자는 함께 묶어야합니다.하스켈의 재귀 토크 나이저

예 보여준다

tokenize "a + b* 12-def" "+-*" " " 

출력해야

["a", "+", "b", "*", "12", "-", "def"] 

tokenize :: String -> String -> String -> [String] 
tokenize [] _ _ = [] 
tokenize [x] _ _ = [[x]] 
tokenize (x:xs) a b  | x `elem` a = [x] : tokenize xs a b 
         | x `elem` b = tokenize xs a b 
         | otherwise = (x:head rest) : tail rest 
           where 
             rest = tokenize xs a b 

그것은 다소 동작이 문제의 예에 해당 사업자 인 아래 내 현재 코드 그 앞에 오는 서신과 함께 번들로 제공됩니다. 별도의 문자열에있는 연산자에도 불구하고이

["a+","b*","12-","def"] 

같은

.

+2

문제는'| 그렇지 않으면 = (x : 머리 받침대) : 꼬리 받침대''머리 받침대 '에'x '를 놓으면 머리 받침대가 무엇이든 상관 없습니다. – sjakobi

답변

1

우선 은 [] 일 때 ["a"]으로 끝나기 때문에 tokenize [x] _ _은 아마도 원하는 것이 아닙니다. 둘째, 분리 자 및 제거 목록 String을 호출하지 마십시오. 그들은 단지 [Char]입니다. 아래에는 아무런 차이가 없습니다. 왜냐하면 type String = [Char]이기 때문에 동의어의 의미는 의미를 더 명확하게하는 것이고 StringString으로 실제로 사용하지 않으므로 귀하의 기능에 적합하지 않습니다. 또한, currying을 쉽게하기 때문에 인수를 tokenize seps rems str으로 셔플해야합니다. 마지막으로 [Char] 대신 Data.Set을 사용하고 싶지만 여기서는 질문에 더 가까이 접근하지 않겠습니다.

문제 자체는 | otherwise = (x:head rest) : tail rest입니다.이 토큰은 토큰이 분리 기호라고해도 다음 토큰으로 불특정 문자를 집어 넣습니다. 귀하의 경우,이 예는 head rest = "+"x = 'a' 일 때입니다. 따라서 귀하는 합쳐서 "a+"이됩니다. 당신은 더 멀리 지켜야합니다.

tokenize :: [Char] -> [Char] -> String -> [String] 
tokenize _ _ "" = [] 
tokenize seps rems (x:xs) 
    | x `elem` rems      = rest 
    | x `elem` seps      = [x]:rest 
    -- Pattern guard: if rest has a single-char token on top and that token is a sep... 
    | ([sep]:_) <- rest, sep `elem` seps = [x]:rest 
    -- Otherwise, if rest has a token on top (which isn't a sep), grow it 
    | (growing:rest') <- rest   = (x:growing):rest' 
    -- Or else make a new token (when rest = []) 
    | otherwise       = [x]:rest 
    where rest = tokenize xs seps rems 

당신은 할 수있다 (또한 : where 조항이 전체 식 바인딩, 그래서 모든 경비를 통하여 볼 수 있어요 그것은 그 분명 그런 들여 쓰기를해야한다 : 당신의 들여 쓰기가 엉망이된다.). 또한 filter을 사용하십시오 :

tokenize seps rems = tokenize' . filter (not . flip elem rems) 
    where tokenize' "" = [] 
     tokenize' (x:xs) 
      | x `elem` seps      = [x]:rest 
      | ([sep]:_) <- rest, sep `elem` seps = [x]:rest 
      | (growing:rest') <- rest   = (x:growing):rest' 
      | otherwise       = [x]:rest 
      where rest = tokenize' xs 
관련 문제