2016-10-28 12 views

答えて

3

標準ライブラリに便利なsplit関数はありません。したがって、本質的にあなた自身をロールバックする必要があります。一つのアプローチ:

import Data.List.Split (splitOn) 
import Data.List (intercalate) 
dropAfter n d = intercalate [d] . take n . splitOn [d] 
3

倍の悪魔のストライキを再び:

dropAfter :: Int -> Char -> String -> String 

dropAfter _ _ "" = "" 
dropAfter 0 d (x:xs) = "" 
dropAfter 1 d (x:xs) | x == d = "" 
dropAfter n d (x:xs) | x == d = x : dropAfter (n-1) d xs 
        | otherwise = x : dropAfter n d xs 

splitパッケージは、しかし、splitOn :: Eq a => [a] -> [a] -> [[a]]を提供します。

dropAfter :: Int -> (a -> Bool) -> [a] -> [a] 
dropAfter n _ _ | n < 1 = [] 
dropAfter n f xs = foldr go (`seq` []) xs n where 
    go x r !k 
    | f x = if k == 1 then [] else x : r (k - 1) 
    | otherwise = x : r k 
+0

なぜ 'const']ではなく '(\' seq \ '[])'ですか? – rampion

+1

@rampion、私はできる限り、厳密性分析(したがってアンボクシング)を手助けするのが私の習慣です。その「seq」は、更新されたアキュムレータの値が常に要求されることを保証する。この場合は必要ではないかもしれませんが、 'const 'と似た形が十分に複雑な文脈になると面白くなります。 – dfeuer

1

代わりに、あなたはパーサを使用して起動する足がかりとしてこれを使用することができます:

λ import Text.Parsec 
λ runParser (many (noneOf "-") `sepBy` char '-')() "example from question" "2016-01-43" 
Right ["2016","01","43"] 
λ import Data.List 
λ intercalate "-" . take 2 <$> it 
Right "2016-01" 

今スイッチを作るのいいところは、あなたがあなたの入力(とものについての詳細を学ぶように、ということですそれは見えるようにすることもできないこともあります)、パーサーを一致させるためにパーサーを更新するのはかなり簡単です。

関連する問題