有没有什么办法可以将最后一次出现给定角色的Haskell中的String拆分成2个列表? 例如,我想拆分列表" a b c d e"在太空中(" a b c d"," e")。 谢谢你的回答。
答案 0 :(得分:5)
我不确定为什么建议的解决方案如此复杂。只需 一次两次遍历:
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!"
答案 1 :(得分:2)
它不漂亮,但它有效:
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")
,但我自己不会裁掉这个尾随空间。
答案 2 :(得分:2)
我会选择更多模式匹配。
import Data.List
splitLast = contract . words
where contract [] = ("", "")
contract [x] = (x, "")
contract [x,y] = (x, y)
contract (x:y:rest) = contract $ intercalate " " [x,y] : rest
对于长列表,我们只使用空格加入前两个字符串并再次尝试较短的列表。一旦长度减少到2,我们就会返回这对字符串。
对于没有空格的字符串, (x, "")
似乎是一个合理的选择,但我想你可以返回("", x)
。
不清楚("", "")
是空字符串的最佳选择,但它似乎是提出错误或将返回类型更改为Maybe (String, String)
之类的合理替代方法。
答案 3 :(得分:1)
我可以提出以下解决方案:
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
替换为length list
答案 4 :(得分:1)
我的想法是在每次出现时拆分,然后将初始部分与最后一部分分开。
尖头:
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