Haskell 使用char或int拆分字符串/列表
我试图在Haskell中创建一个函数,将字符串拆分为某个字符,并将列表拆分为某个数字 为了做到这一点,splitAt函数正是我需要的数字,但我不能用这个函数给出一个字符 例如 给予 这正是我需要的元组左侧的5。 但是现在我想用一个Haskell 使用char或int拆分字符串/列表,haskell,Haskell,我试图在Haskell中创建一个函数,将字符串拆分为某个字符,并将列表拆分为某个数字 为了做到这一点,splitAt函数正是我需要的数字,但我不能用这个函数给出一个字符 例如 给予 这正是我需要的元组左侧的5。 但是现在我想用一个char和一个字符串来实现这一点。但是对于第二个参数,splitAt只接受和int。我想要 splitAt 'c' "abcde" 导致 ("abc", "de") 我在寻找一个方向的东西 splitAt
char
和一个字符串来实现这一点。但是对于第二个参数,splitAt
只接受和int
。我想要
splitAt 'c' "abcde"
导致
("abc", "de")
我在寻找一个方向的东西
splitAt (findIndex 'c' "abcde") "abcde"
但是函数findIndex
返回的类型可能是Int,splitAt
需要一个Int
。然后我尝试了以下方法
splitAt (head (findIndices (== 'c') "abcde")) "abcde"
("ab","cde")
这是一个可能的解决方案,但它返回以下内容
splitAt (head (findIndices (== 'c') "abcde")) "abcde"
("ab","cde")
c在元组的错误一侧。您可以将succ
添加到c中,但是如果字符是Z,结果会是什么呢
有没有一个简单的方法来修改以使
splitAt (findIndex 'c' "abcde") "abcde"
工作?您可以使用
findIndex
,只需打开可能
并添加一个:
import Data.List
splitAfter :: (a-> Bool) -> [a] -> ([a],[a])
splitAfter this xs = case findIndex this xs of
Nothing -> (xs,[])
Just n -> splitAt (n+1) xs
例如,给予
*Main> splitAfter (=='c') "abcde"
("abc","de")
*Main> splitAfter' (==5) [1..10]
([1,2,3,4,5],[6,7,8,9,10])
可能是一种方便的数据类型,用于以易于恢复的方式对故障进行编码。甚至还有一个函数maybe::b->(a->b)->maybe a->b
使用默认值和一个函数分别处理这两种情况:
splitAfter' :: (a-> Bool) -> [a] -> ([a],[a])
splitAfter' this xs = maybe (xs,[])
(\n -> splitAt (n+1) xs)
(findIndex this xs)
这同样有效。比如说
*Main> splitAfter (=='c') "abcde"
("abc","de")
*Main> splitAfter' (==5) [1..10]
([1,2,3,4,5],[6,7,8,9,10])
您可以使用
fromaybe
函数从Maybe获取结果,例如:
splitlist = splitAt (fromMaybe 0 (findIndex 'c' "abcde") "abcde")
fromaybe::a->Maybe a->a
fromMaybe函数接受默认值和Maybe值。如果
可能为空,返回默认值;否则,
返回函数中包含的值。()
默认值设置为0时,如果findIndex返回
Nothing
,则splitAt的结果将是(“”,list)
,对于相同的情况,但默认值设置为length list
,则最终结果将是(list,“”)
给定的c::Char
和s::String
,你可以写一些
splitAt ((1+) $ fromJust $ findIndex (==c) s) s
但是
c
未进入s
s
两次可能
的替代方案是
maybe Nothing (\x -> splitAt (1+x) s) (findIndex (==c) s)
您可以设置“其他值”(Nothing
,在我的示例中)
您可以将自己的函数编写为
splitAt' :: Char -> String -> (String, String)
splitAt' _ [] = ("", "")
splitAt' c (x:xs) | c == x = ([c], xs)
| True = (x:cs, ys) where (cs, ys) = splitAt' c xs
然后,如果不是
s
中的(s,“”)
,您将得到,
,这里有一种不同的方法,它不涉及混淆列表索引
break
几乎就是你想要的。让我们重复使用它。您希望匹配元素包含在第一个输出列表的末尾,而不是第二个输出列表的开头
import Control.Arrow ((***))
breakAfter :: (a -> Bool) -> [a] -> ([a], [a])
breakAfter p xs = map fst *** map fst $ break snd (zip xs $ False : map p xs)
工作原理:
zip
)。每对的第一个元素取自原始列表。该对中的第二个元素是一个Bool
,说明列表中的前一个元素是否是我们要查找的元素。这就是为什么我们说False:map p xs
——如果我们只是说map p xs
,我们将准确地再现break
的行为。在开始时插入额外的False
,这一点很重要break
。我们的条件编码在每对的第二个元素中Bool
s。我们不再需要他们了如果您使用
::(a->Bool)->[a]->([a],[a])
而不是splitAt
,则不需要findIndex
@SebastianPaaskeTørholm,但您可以在右侧而不是左侧获得'c'
。