在Haskell中,有没有一种方法可以在给定字符的最后一个出现位置上将字符串分割成两个列表?例如,我想在空格上将列表"a b c d e"分割成 ("a b c d", "e") 两部分。
感谢您的回答。
splitLast :: Eq a => a -> [a] -> Either [a] ([a],[a])
splitLast c' = foldr go (Left [])
where
go c (Right (f,b)) = Right (c:f,b)
go c (Left s) | c' == c = Right ([],s)
| otherwise = Left (c:s)
请注意,这是完整的并明显表示它的失败。当无法进行拆分(因为指定的字符不在字符串中)时,它会返回一个带有原始列表的Left
。否则,它将返回一个带有两个组件的Right
。
ghci> splitLast ' ' "hello beautiful world"
Right ("hello beautiful","world")
ghci> splitLast ' ' "nospaceshere!"
Left "nospaceshere!"
它不够美观,但是它能够正常工作:
import Data.List
f :: Char -> String -> (String, String)
f char str = let n = findIndex (==char) (reverse str) in
case n of
Nothing -> (str, [])
Just n -> splitAt (length str - n -1) str
f 'e' "a b c d e" = ("a b c d ", "e")
,但我自己不会删除结尾的空格。a -> [a] -> ([a], [a])
,是吧? - Chris Martinimport Data.List
splitLast = contract . words
where contract [] = ("", "")
contract [x] = (x, "")
contract [x,y] = (x, y)
contract (x:y:rest) = contract $ intercalate " " [x,y] : rest
(x,"")
似乎是一个合理的选择,但我想你可以返回("",x)
。("","")
不清楚是否是最佳选择,但它似乎是将返回类型更改为Maybe (String, String)
或引发错误的合理替代方案。splitLast list elem = (reverse $ snd reversedSplit, reverse $ fst reversedSplit)
where
reversedSplit = span (/= elem) $ reverse list
可能不是最快的方法(有两个不必要的反转),但我喜欢它的简单性。
如果你坚持要去掉我们分割的空格,可以选择:
import qualified Data.List as List
splitLast list elem = splitAt (last $ List.elemIndices elem list) list
import qualified Data.List as List
splitLast list elem = splitAt index list where
index = if null indices then 0 else last indices
indices = List.elemIndices elem list
0
替换为list长度
。import Control.Arrow -- (&&&)
import Data.List -- intercalate
import Data.List.Split -- splitOn
breakOnLast :: Eq a => a -> [a] -> ([a], [a])
breakOnLast x = (intercalate x . init &&& last) . splitOn x
无参函数:
liftA2 (.) ((&&& last) . (. init) . intercalate) splitOn
(.) <$> ((&&&) <$> ((.) <$> pure init <*> intercalate) <*> pure last) <*> splitOn
Data.List.Split
是由 split
包提供的。 - chepner
breakLastSpace str = (reverse (drop 1 y), reverse x) where (x, y) = break (== ' ') $ reverse str
是一个相对比较简单的实现。 - Alexis Kingtext
具有breakOnEnd :: Text -> Text -> (Text, Text)
,因此T.breakOnEnd " " "a b c d e"
会给出所需的结果("a b c d ","e")
。 - Michael